Mercurial > hg > dmlib
diff src/dmcurves.c @ 976:1b439304ff3c
Add new module dmcurves, that will contain functions for spline generation
etc and the LERP functions. Move LERP functions from dmlib.h to dmcurves.h.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 27 Feb 2015 16:16:59 +0200 |
parents | |
children | fecf3967abee |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dmcurves.c Fri Feb 27 16:16:59 2015 +0200 @@ -0,0 +1,75 @@ +/* + * DMLib + * -- Curve and spline functions + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2015 Tecnic Software productions (TNSP) + */ +#include "dmcurves.h" + + +static inline const DMVector *dmSplineGetPoint(const DMVector *points, const int npoints, const int n) +{ + return (n < 0) ? &points[0] : ((n < npoints) ? &points[n] : &points[npoints - 1]); +} + + +int dmBSplineGenerate(DMVector *dst, const int ndst, const DMVector *points, const int npoints, const int slod) +{ + int cv, j; + DMVector *curr = dst; + + for (cv = -3, j = 0; j != npoints + 1 && j < ndst; j++, cv++, curr++) + { + // for each section of curve, draw 'lod' number of divisions + int i; + for (i = 0; i != slod; i++) + { + // use the parametric time value 0.0 to 1.0 for this curve segment + const float t = (float) i / slod; + + // inverse value of 't' + const float it = 1.0f - t; + + // calculate blending functions for cubic bspline + const float t2 = t * t; + const float t3 = t2 * t; + const float b0 = it * it * it / 6.0f; + const float b1 = ( 3*t3 - 6*t2 + 4) / 6.0f; + const float b2 = (-3*t3 + 3*t2 + 3*t + 1) / 6.0f; + const float b3 = t3 / 6.0f; + + // calculate the x,y and z of the curve point + curr->x = b0 * dmSplineGetPoint(points, npoints, cv + 0)->x + + b1 * dmSplineGetPoint(points, npoints, cv + 1)->x + + b2 * dmSplineGetPoint(points, npoints, cv + 2)->x + + b3 * dmSplineGetPoint(points, npoints, cv + 3)->x; + + curr->y = b0 * dmSplineGetPoint(points, npoints, cv + 0)->y + + b1 * dmSplineGetPoint(points, npoints, cv + 1)->y + + b2 * dmSplineGetPoint(points, npoints, cv + 2)->y + + b3 * dmSplineGetPoint(points, npoints, cv + 3)->y; + + curr->z = b0 * dmSplineGetPoint(points, npoints, cv + 0)->z + + b1 * dmSplineGetPoint(points, npoints, cv + 1)->z + + b2 * dmSplineGetPoint(points, npoints, cv + 2)->z + + b3 * dmSplineGetPoint(points, npoints, cv + 3)->z; + } + } + + return (j == ndst) ? DMERR_OK : DMERR_BOUNDS; +} + + +int dmBSplineGenerateAlloc(DMVector **dst, int *ndst, const DMVector *points, const int npoints, const int slod) +{ + if (ndst == NULL || dst == NULL) + return DMERR_NULLPTR; + + if ((*ndst = dmBSplineGetNPoints(npoints, slod)) <= 0) + return DMERR_INVALID_DATA; + + if ((*dst = dmCalloc(*ndst, sizeof(DMVector))) == NULL) + return DMERR_MALLOC; + + return dmBSplineGenerate(*dst, *ndst, points, npoints, slod); +}