# HG changeset patch # User Matti Hamalainen # Date 1425046619 -7200 # Node ID 1b439304ff3ce26bae5c79ba5b4d2e823efdbce2 # Parent 139b801f8d1cdf7e3fb63a07631fb6f9b176d452 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. diff -r 139b801f8d1c -r 1b439304ff3c Makefile.gen --- a/Makefile.gen Fri Feb 27 14:49:02 2015 +0200 +++ b/Makefile.gen Fri Feb 27 16:16:59 2015 +0200 @@ -278,7 +278,7 @@ DMLIB_OBJS += \ dmfile.o dmbstr.o dmlib.o dmlerp.o dmstring.o \ dmargs.o dmvecmat.o dmperlin.o dmimage.o \ - dmwav.o dmengine.o dmfft.o dmzlib.o + dmwav.o dmcurves.o dmengine.o dmfft.o dmzlib.o TESTS_TARGETS = $(addprefix $(TESTS_BINPATH),$(addsuffix $(EXEEXT),$(TESTS_BINARIES))) diff -r 139b801f8d1c -r 1b439304ff3c src/dmcurves.c --- /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); +} diff -r 139b801f8d1c -r 1b439304ff3c src/dmcurves.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dmcurves.h Fri Feb 27 16:16:59 2015 +0200 @@ -0,0 +1,93 @@ +/* + * DMLib + * -- Wav file writing + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) + */ +#ifndef DMCURVES_H +#define DMCURVES_H + +#include "dmlib.h" +#include "dmvecmat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generic parameter interpolation + */ +#define DMM_S_CURVE(t) ((t) * (t) * (3.0f - 2.0f * (t))) +#define DMM_LERP(t, a, b) ((a) + (t) * ((b) - (a))) + +typedef struct +{ + DMFloat start, end, nsteps; +} DMLerpContext; + + +void dmLerpInit(DMLerpContext *ctx, DMFloat start, DMFloat end, DMFloat nsteps); +DMFloat dmCatmullRom(const DMFloat t, const DMFloat p0, const DMFloat p1, const DMFloat p2, const DMFloat p3); + + +static inline DMFloat dmClamp10(const DMFloat a) +{ + return (a < 0.0f ? 0.0f : (a > 1.0f ? 1.0f : a)); +} + + +static inline int dmClamp(const int v, const int min, const int max) +{ + return (v < min ? min : (v > max ? max : v)); +} + + +static inline DMFloat dmLerpSCurve(DMLerpContext *ctx, const DMFloat step) +{ + const DMFloat n = step / ctx->nsteps; + const DMFloat v = DMM_S_CURVE(n); + return DMM_LERP(v, ctx->start, ctx->end); +} + + +static inline DMFloat dmLerpSCurveClamp(DMLerpContext *ctx, const DMFloat step) +{ + const DMFloat n = dmClamp10(step / ctx->nsteps); + const DMFloat v = DMM_S_CURVE(n); + return DMM_LERP(v, ctx->start, ctx->end); +} + + +static inline DMFloat dmLerp1(DMLerpContext *ctx, const DMFloat step) +{ + const DMFloat v = step / ctx->nsteps; + return DMM_LERP(v, ctx->start, ctx->end); +} + + +static inline DMFloat dmLerp1Clamp(DMLerpContext *ctx, const DMFloat step) +{ + const DMFloat v = dmClamp10(step / ctx->nsteps); + return DMM_LERP(v, ctx->start, ctx->end); +} + + +static inline DMFloat dmCatmullRomClamp(const DMFloat t, const DMFloat p0, const DMFloat p1, const DMFloat p2, const DMFloat p3) +{ + return dmCatmullRom(dmClamp10(t), p0, p1, p2, p3); +} + + +static inline int dmBSplineGetNPoints(const int npoints, const int slod) +{ + return npoints * slod; +} + +int dmBSplineGenerateAlloc(DMVector **dst, int *ndst, const DMVector *points, const int npoints, const int slod); +int dmBSplineGenerate(DMVector *dst, const int ndst, const DMVector *points, const int npoints, const int slod); + + +#ifdef __cplusplus +} +#endif + +#endif // DMCURVES_H diff -r 139b801f8d1c -r 1b439304ff3c src/dmlib.h --- a/src/dmlib.h Fri Feb 27 14:49:02 2015 +0200 +++ b/src/dmlib.h Fri Feb 27 16:16:59 2015 +0200 @@ -206,69 +206,6 @@ } -/* Generic parameter interpolation - */ -#define DMM_S_CURVE(t) ((t) * (t) * (3.0f - 2.0f * (t))) -#define DMM_LERP(t, a, b) ((a) + (t) * ((b) - (a))) - -typedef struct -{ - DMFloat start, end, nsteps; -} DMLerpContext; - - -void dmLerpInit(DMLerpContext *ctx, DMFloat start, DMFloat end, DMFloat nsteps); -DMFloat dmCatmullRom(const DMFloat t, const DMFloat p0, const DMFloat p1, const DMFloat p2, const DMFloat p3); - - -static inline DMFloat dmClamp10(const DMFloat a) -{ - return (a < 0.0f ? 0.0f : (a > 1.0f ? 1.0f : a)); -} - - -static inline int dmClamp(const int v, const int min, const int max) -{ - return (v < min ? min : (v > max ? max : v)); -} - - -static inline DMFloat dmLerpSCurve(DMLerpContext *ctx, const DMFloat step) -{ - const DMFloat n = step / ctx->nsteps; - const DMFloat v = DMM_S_CURVE(n); - return DMM_LERP(v, ctx->start, ctx->end); -} - - -static inline DMFloat dmLerpSCurveClamp(DMLerpContext *ctx, const DMFloat step) -{ - const DMFloat n = dmClamp10(step / ctx->nsteps); - const DMFloat v = DMM_S_CURVE(n); - return DMM_LERP(v, ctx->start, ctx->end); -} - - -static inline DMFloat dmLerp1(DMLerpContext *ctx, const DMFloat step) -{ - const DMFloat v = step / ctx->nsteps; - return DMM_LERP(v, ctx->start, ctx->end); -} - - -static inline DMFloat dmLerp1Clamp(DMLerpContext *ctx, const DMFloat step) -{ - const DMFloat v = dmClamp10(step / ctx->nsteps); - return DMM_LERP(v, ctx->start, ctx->end); -} - - -static inline DMFloat dmCatmullRomClamp(const DMFloat t, const DMFloat p0, const DMFloat p1, const DMFloat p2, const DMFloat p3) -{ - return dmCatmullRom(dmClamp10(t), p0, p1, p2, p3); -} - - /* Arbitrary line drawing */ #ifdef DM_GFX_LINES