nuclear@0: #include nuclear@0: #include nuclear@0: #include "curve.h" nuclear@0: #include "opengl.h" nuclear@0: #include "shader.h" nuclear@0: #include "logger.h" nuclear@0: nuclear@0: #define DEF_THICKNESS 0.075 nuclear@0: #define DEF_SEGM_SUB 3 nuclear@0: #define DEF_RING_SUB 6 nuclear@0: nuclear@0: Curve::Curve() nuclear@0: { nuclear@0: thickness = DEF_THICKNESS; nuclear@0: mesh_valid = false; nuclear@0: lengths_valid = false; nuclear@0: nuclear@0: bbox_valid = false; nuclear@0: nuclear@0: segm_subdiv = DEF_SEGM_SUB; nuclear@0: ring_subdiv = DEF_RING_SUB; nuclear@0: } nuclear@0: nuclear@0: Curve::Curve(const Vector3 *points, int num_points) nuclear@0: { nuclear@0: thickness = DEF_THICKNESS; nuclear@0: mesh_valid = false; nuclear@0: lengths_valid = false; nuclear@0: nuclear@0: bbox_valid = false; nuclear@0: nuclear@0: segm_subdiv = DEF_SEGM_SUB; nuclear@0: ring_subdiv = DEF_RING_SUB; nuclear@0: nuclear@0: for(int i=0; iname = name; nuclear@0: } nuclear@0: nuclear@0: const char *Curve::get_name() const nuclear@0: { nuclear@0: return name.c_str(); nuclear@0: } nuclear@0: nuclear@0: bool Curve::empty() const nuclear@0: { nuclear@0: return cv.empty(); nuclear@0: } nuclear@0: nuclear@0: void Curve::set_thickness(float thickness) nuclear@0: { nuclear@0: this->thickness = thickness; nuclear@0: } nuclear@0: nuclear@0: void Curve::set_subdiv(int seg, int ring) nuclear@0: { nuclear@0: if(seg < 1) seg = 1; nuclear@0: if(ring < 3) ring = 3; nuclear@0: nuclear@0: segm_subdiv = seg; nuclear@0: ring_subdiv = ring; nuclear@0: } nuclear@0: nuclear@0: void Curve::clear() nuclear@0: { nuclear@0: mesh_valid = false; nuclear@0: lengths_valid = false; nuclear@0: bbox_valid = false; nuclear@0: cv.clear(); nuclear@0: } nuclear@0: nuclear@0: void Curve::add_point(const Vector3 &pt) nuclear@0: { nuclear@0: cv.push_back(pt); nuclear@0: mesh_valid = false; nuclear@0: lengths_valid = false; nuclear@0: bbox_valid = false; nuclear@0: } nuclear@0: nuclear@0: Vector3 &Curve::get_point(int idx) nuclear@0: { nuclear@0: mesh_valid = false; nuclear@0: lengths_valid = false; nuclear@0: bbox_valid = false; nuclear@0: return cv[idx]; nuclear@0: } nuclear@0: nuclear@0: const Vector3 &Curve::get_point(int idx) const nuclear@0: { nuclear@0: return cv[idx]; nuclear@0: } nuclear@0: nuclear@0: int Curve::get_count() const nuclear@0: { nuclear@0: return (int)cv.size(); nuclear@0: } nuclear@0: nuclear@0: Vector3 &Curve::operator[] (int idx) nuclear@0: { nuclear@0: return get_point(idx); nuclear@0: } nuclear@0: nuclear@0: const Vector3 &Curve::operator[] (int idx) const nuclear@0: { nuclear@0: return get_point(idx); nuclear@0: } nuclear@0: nuclear@0: void Curve::get_bbox(Vector3 *bbmin, Vector3 *bbmax) const nuclear@0: { nuclear@0: if(!bbox_valid) { nuclear@0: this->bbmin = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); nuclear@0: this->bbmax = -this->bbmin; nuclear@0: nuclear@0: for(size_t i=0; ibbmin[j]) { nuclear@0: this->bbmin[j] = cv[i][j]; nuclear@0: } nuclear@0: if(cv[i][j] > this->bbmax[j]) { nuclear@0: this->bbmax[j] = cv[i][j]; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: bbox_valid = true; nuclear@0: } nuclear@0: nuclear@0: if(bbmin) *bbmin = this->bbmin; nuclear@0: if(bbmax) *bbmax = this->bbmax; nuclear@0: } nuclear@0: nuclear@0: void Curve::normalize() nuclear@0: { nuclear@0: get_bbox(0, 0); // force validation of the bounding box nuclear@0: nuclear@0: float len = (bbmax - bbmin).length() * 0.5; nuclear@0: if(len == 0.0) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: for(size_t i=0; i= 1.0) { nuclear@0: return cv.back(); nuclear@0: } nuclear@0: nuclear@0: t = reparametrize(t); nuclear@0: nuclear@0: int numcv = (int)cv.size(); nuclear@0: int idx0 = t * (numcv - 1); nuclear@0: int idx1 = idx0 + 1; nuclear@0: nuclear@0: int idx_prev = idx0 <= 0 ? idx0 : idx0 - 1; nuclear@0: int idx_next = idx1 >= numcv - 1 ? idx1 : idx1 + 1; nuclear@0: nuclear@0: float dt = 1.0 / (float)(numcv - 1); nuclear@0: 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: //return catmull_rom_spline(cv[idx_prev], cv[idx0], cv[idx1], cv[idx_next], t); nuclear@0: return bspline(cv[idx_prev], cv[idx0], cv[idx1], cv[idx_next], t); nuclear@0: } nuclear@0: nuclear@0: Vector3 Curve::operator() (float t) const nuclear@0: { nuclear@0: return get_pos(t); nuclear@0: } nuclear@0: nuclear@0: void Curve::draw() const nuclear@0: { nuclear@0: update_mesh(); nuclear@0: if(!mesh_valid) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: mesh.draw(); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: float Curve::reparametrize(float t) const nuclear@0: { nuclear@0: calc_cvlengths(); nuclear@0: return t; // TODO nuclear@0: } nuclear@0: nuclear@0: void Curve::calc_cvlengths() const nuclear@0: { nuclear@0: if(lengths_valid || cv.empty()) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: length.clear(); nuclear@0: length.resize(cv.size()); nuclear@0: nuclear@0: length[0] = 0; nuclear@0: for(size_t i=1; i