// DescriptionHere - common.cpp
// Created by John Ryland (jryland@xiaofrog.com), 03/11/2017
// Copyright (c) 2017 InvertedLogic
// All rights reserved.
#include <pthread.h>
#include <unistd.h>
#include "common.h"
void startThread(void*(*func)(void*), void* user)
{
pthread_t thread;
pthread_create(&thread, NULL, func, user);
}
void sleepMilli(int milliSeconds)
{
usleep(milliSeconds*1000);
}
vec2f operator*(const vec2f& v, float c)
{
return (vec2f){ v.x*c, v.y*c };
}
vec2f operator*(float c, const vec2f& v)
{
return (vec2f){ v.x*c, v.y*c };
}
vec2f operator+(const vec2f& v1, const vec2f& v2)
{
return (vec2f){ v1.x+v2.x, v1.y+v2.y };
}
// Simple 3 control point bezier curve
vec2i bezierCurve(const vec2i& p1, const vec2i& p2, const vec2i& p3, float t)
{
float t2 = 1.0f - t;
return (vec2i){ int(t2*t2*p1.x + 2.0*t2*t*p2.x + t*t*p3.x),
int(t2*t2*p1.y + 2.0*t2*t*p2.y + t*t*p3.y) };
}
// Generalized spline function
vec2f kochanekBartelsSpline(const std::vector<vec2f>& a_points, float t, float a_tension, float a_bias, float a_continuity)
{
int pnts = a_points.size();
if (!pnts)
return (vec2f){ 0.0f, 0.0f };
t = std::max(0.0f, std::min(1.0f, t)); // clamp t to be between 0->1
int intervals = pnts - 1; // the intervals are the segments between each point
int n = std::max(0, std::min(pnts-1, int(intervals * t))); // figure out which interval t is between
t = t * intervals - n; // the new t value is the ratio between the points at n and n+1
float tmp1 = 0.5f * (1.0f - a_tension);
float A = tmp1 * (1.0f + a_continuity) * (1.0f + a_bias); // A,B,C,D are the parameter factors
float B = tmp1 * (1.0f - a_continuity) * (1.0f - a_bias);
float C = tmp1 * (1.0f - a_continuity) * (1.0f + a_bias);
float D = tmp1 * (1.0f + a_continuity) * (1.0f - a_bias);
const vec2f& pnt0 = a_points[std::max(n - 1, 0)];
const vec2f& pnt1 = a_points[n];
const vec2f& pnt2 = a_points[std::min(pnts - 1, n + 1)];
const vec2f& pnt3 = a_points[std::min(pnts - 1, n + 2)];
vec2f vA = -A*pnt0 + (2+A-B-C)*pnt1 + (-2+B+C-D)*pnt2 + D*pnt3; // vA,vB,vC - polynomial factors
vec2f vB = 2*A*pnt0 + (-3-2*A+2*B+C)*pnt1 + (3-2*B-C+D)*pnt2 + -D*pnt3;
vec2f vC = -A*pnt0 + (A-B)*pnt1 + B*pnt2;
return ((vA*t + vB)*t + vC)*t + pnt1; // blends by the factors between the 4 closest control points
}
vec2f catmulRomSpline(const std::vector<vec2f>& a_points, float t)
{
return kochanekBartelsSpline(a_points, t, 0.0f, 0.0f, 0.0f);
}
vec2f cubicSpline(const std::vector<vec2f>& a_points, float t)
{
return kochanekBartelsSpline(a_points, t, 1.0f, 0.0f, 0.0f);
}
vec2f lineSpline(const std::vector<vec2f>& a_points, float t)
{
return kochanekBartelsSpline(a_points, t, 0.0f, 0.0f, -1.0f);
}