nuclear@0: #include nuclear@0: #include "curve.h" nuclear@0: nuclear@0: Curve::Curve(CurveType type) nuclear@0: { nuclear@0: this->type = type; nuclear@0: } nuclear@0: nuclear@0: void Curve::set_type(CurveType type) nuclear@0: { nuclear@0: this->type = type; nuclear@0: } nuclear@0: nuclear@0: CurveType Curve::get_type() const nuclear@0: { nuclear@0: return type; nuclear@0: } nuclear@0: nuclear@0: void Curve::add_point(const Vector2 &p, float weight) nuclear@0: { nuclear@0: cp.push_back(Vector3(p.x, p.y, weight)); nuclear@0: } nuclear@0: nuclear@0: bool Curve::remove_point(int idx) nuclear@0: { nuclear@0: if(idx < 0 || idx >= (int)cp.size()) { nuclear@0: return false; nuclear@0: } nuclear@0: cp.erase(cp.begin() + idx); nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: int Curve::nearest_point(const Vector2 &p) nuclear@0: { nuclear@0: int res = -1; nuclear@0: float bestsq = FLT_MAX; nuclear@0: nuclear@0: for(size_t i=0; i= (int)cp.size()) { nuclear@0: return false; nuclear@0: } nuclear@0: cp[idx] = Vector3(p.x, p.y, weight); nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: bool Curve::set_weight(int idx, float weight) nuclear@0: { nuclear@0: if(idx < 0 || idx >= (int)cp.size()) { nuclear@0: return false; nuclear@0: } nuclear@0: cp[idx].z = weight; nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@2: bool Curve::move_point(int idx, const Vector2 &p) nuclear@2: { nuclear@2: if(idx < 0 || idx >= (int)cp.size()) { nuclear@2: return false; nuclear@2: } nuclear@2: cp[idx] = Vector3(p.x, p.y, cp[idx].z); nuclear@2: return true; nuclear@2: } nuclear@2: nuclear@0: Vector2 Curve::interpolate(float t, CurveType type) const nuclear@0: { nuclear@2: if(cp.empty()) { nuclear@0: return Vector2(0, 0); nuclear@0: } nuclear@2: nuclear@2: int num_cp = (int)cp.size(); nuclear@0: if(num_cp == 1) { nuclear@0: return Vector2(cp[0].x, cp[0].y); nuclear@0: } nuclear@0: nuclear@0: Vector3 res; nuclear@2: int idx0 = std::min((int)floor(t * (num_cp - 1)), num_cp - 2); nuclear@0: int idx1 = idx0 + 1; nuclear@0: nuclear@0: float dt = 1.0 / (float)(num_cp - 1); nuclear@0: float t0 = (float)idx0 * dt; nuclear@0: float t1 = (float)idx1 * dt; nuclear@0: nuclear@0: t = (t - t0) / (t1 - t0); nuclear@0: if(t < 0.0) t = 0.0; nuclear@0: if(t > 1.0) t = 1.0; nuclear@0: nuclear@0: if(type == CURVE_LINEAR || num_cp <= 2) { nuclear@0: res = lerp(cp[idx0], cp[idx1], t); nuclear@0: } else { nuclear@0: int idx_prev = idx0 <= 0 ? idx0 : idx0 - 1; nuclear@0: int idx_next = idx1 >= num_cp - 1 ? idx1 : idx1 + 1; nuclear@0: nuclear@0: if(type == CURVE_HERMITE) { nuclear@0: res = catmull_rom_spline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t); nuclear@0: } else { nuclear@0: res = bspline(cp[idx_prev], cp[idx0], cp[idx1], cp[idx_next], t); nuclear@0: if(res.z != 0.0f) { nuclear@0: res.x /= res.z; nuclear@0: res.y /= res.z; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: return Vector2(res.x, res.y); nuclear@0: } nuclear@0: nuclear@0: Vector2 Curve::interpolate(float t) const nuclear@0: { nuclear@0: return interpolate(t, type); nuclear@0: } nuclear@0: nuclear@0: Vector2 Curve::operator ()(float t) const nuclear@0: { nuclear@0: return interpolate(t); nuclear@0: }