As a part of a class project I’m adding in the ability to animate along a catmull-rom spline. If you want to compile this code you’ll need to download my 3DIO library or simply create your own simplistic vector3 class. All it needs are 3 floats. You’ll also need the handy-dandy CImg library.
#include <3DIO/3DIO.h>
#include
#include
using namespace tdio_library;
using namespace std;
using namespace cimg_library;
double calc_cat(double t, double p0,double p1,double p2,double p3){
double t2 = t*t;
double t3 = t2 * t;
return (0.5 *( (2 * p1) + (-p0 + p2) * t +(2*p0 - 5*p1 + 4*p2 - p3) * t2 +(-p0 + 3*p1- 3*p2 + p3) * t3));
}
void interactive_catmull(){
vector control_pts; ///control point vector
vector draw_pts; ///draw point vector
CImg image(500,400,1,3,0); ///main image
unsigned char red[] = {255,0,0}; ///color red
image.fill(0);
CImgDisplay main_disp(image,"Click a point");
int lastPt = 0;
while (!main_disp.is_closed) {
main_disp.wait();
if (main_disp.button && main_disp.mouse_y>=0) {
const int y = main_disp.mouse_y;
const int x = main_disp.mouse_x;
control_pts.push_back(vector3(x,y,0));
if(lastPt + 4 <= control_pts.size()){
draw_pts.clear();
vector3 p0,p1,p2,p3;
p0 = control_pts[lastPt];
p1 = control_pts[lastPt+1];
p2 = control_pts[lastPt+2];
p3 = control_pts[lastPt+3];
///We have enough pts(4 <= N <= INF)
for(float i = 0; i <= 1; i+=0.01){
vector3 pt;
pt.x = calc_cat(i,p0.x,p1.x,p2.x,p3.x);
pt.y = calc_cat(i,p0.y,p1.y,p2.y,p3.y);
pt.z = calc_cat(i,p0.z,p1.z,p2.z,p3.z);
draw_pts.push_back(pt);
}
for(int i = 0; i < draw_pts.size()-1; i++){
image.draw_line((int)draw_pts[i].x,(int)draw_pts[i].y,(int)draw_pts[i+1].x,(int)draw_pts[i+1].y,red);
}
lastPt++;
}
image.draw_circle(x,y,2,red);
}
main_disp.display(image);
}
}
Keep in mine you need 4 control points to define a curve and the curve is only drawn between Pt[1] and Pt[2] of each segment. This page has a nice graph and explanation.