view 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 source

/*
 * 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);
}