#if !defined(GRANNY_BSPLINE_H)
#include "header_preamble.h"
// ========================================================================
// $File: //jeffr/granny/rt/granny_bspline.h $
// $DateTime: 2006/10/16 14:57:23 $
// $Change: 13583 $
// $Revision: #8 $
//
// (C) Copyright 1999-2006 by RAD Game Tools, All Rights Reserved.
// ========================================================================

/* ========================================================================
   This is a utility module that contains most of the common functions
   used to deal with B-Spline fitting and evaluation.  It is not a general
   set of curve utilities, as it supports only non-uniform non-rational
   B-Splines and has no facilities for converting to other closed-form
   curve types or subdivision curves.

   At this time, it only deals with curves in Euclidean space, although
   in the future I may add some spherical B-Spline functions (once I
   actually get the feeling that researchers have worked them out
   sufficiently).

   Some notation:

       w    - the width of the spline (3 - vector, 4 - quaternion, etc.)
       d    - the degree of the spline (2 - quadratic, 3 - cubic, etc.)

       t    - the parameter of the spline function
       ti   - the central knot whose neighborhood is being evaluated
       ti_x - the knot x entries before ti (x is any integer)
       tix  - the knot x entries after ti (x is any integer)

       ci   - the coefficient generated by the knot at ti
       ci_x - the coefficient generated by the knot at ti_x
       cix  - the coefficient generated by the knot at tix

       pi   - the control point at ti
       pi_x - the control point at ti_x
       pix  - the control point at tix

       *ti  - a pointer to an array of knots, where ti[0]
              is the current knot, ti[x] is the xth knot after
              current one, and ti[-x] is the xth knot prior to
              the current one
       *ci  - a pointer to an array of coefficients such that ci[x]
              corresponds to ti[x]
       *pi  - a pointer to an array of control points such that pi[x*w]
              corresponds to ti[x]

   ======================================================================== */

#if !defined(GRANNY_NAMESPACE_H)
#include "granny_namespace.h"
#endif

#if !defined(GRANNY_TYPES_H)
#include "granny_types.h"
#endif

#if !defined(GRANNY_ASSERT_H)
#include "granny_assert.h"
#endif

BEGIN_GRANNY_NAMESPACE EXPGROUP(BSplineGroup);

// Note that ci_1 not given; it's just 1-ci
inline real32 LinearCoefficient(real32 const ti_1,
                                real32 const ti,
                                real32 const t);

inline void LinearCoefficients(real32 const ti_1,
                               real32 const ti,
                               real32 const t,
                               real32 &ci_1,
                               real32 &ci);
inline void QuadraticCoefficients(real32 const ti_2,
                                  real32 const ti_1,
                                  real32 const ti,
                                  real32 const ti1,
                                  real32 const t,
                                  real32 &ci_2,
                                  real32 &ci_1,
                                  real32 &ci);
inline void CubicCoefficients(real32 const ti_3,
                              real32 const ti_2,
                              real32 const ti_1,
                              real32 const ti,
                              real32 const ti1,
                              real32 const ti2,
                              real32 const t,
                              real32 &ci_3,
                              real32 &ci_2,
                              real32 &ci_1,
                              real32 &ci);

// Coefficients() will call the direct coefficient routines when
// it detects that the degree is suitable, and recursively compute
// them otherwise.
void Coefficients(int32x const d,
                  real32 const *ti,
                  real32 const t,
                  real32 *ci);

// Note that the "t" value for 0th-order b-spline sampling is not actually
// necessary - but we include it in the function prototype to ensure that
// all sampling functions are identically typed, in case one should want
// to use table-driven calls.
EXPAPI GS_SAFE void SampleBSpline0x1(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline0x2(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline0x3(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline0x4(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline0x9(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);

EXPAPI GS_SAFE void SampleBSpline1x1(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline1x2(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline1x3(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline1x3n(real32 const *ti, real32 const *pi,
                                      real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline1x4(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline1x4n(real32 const *ti, real32 const *pi,
                                      real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline1x9(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);

EXPAPI GS_SAFE void SampleBSpline2x1(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline2x2(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline2x3(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline2x3n(real32 const *ti, real32 const *pi,
                                      real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline2x4(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline2x4n(real32 const *ti, real32 const *pi,
                                      real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline2x9(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);

EXPAPI GS_SAFE void SampleBSpline3x1(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline3x2(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline3x3(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline3x3n(real32 const *ti, real32 const *pi,
                                      real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline3x4(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline3x4n(real32 const *ti, real32 const *pi,
                                      real32 t, real32 *Result);
EXPAPI GS_SAFE void SampleBSpline3x9(real32 const *ti, real32 const *pi,
                                     real32 t, real32 *Result);

EXPAPI GS_SAFE void SampleBSpline(int32x Degree, int32x Dimension,
                                  bool Normalize,
                                  real32 const *ti, real32 const *pi,
                                  real32 t, real32 *Result);

EXPAPI GS_SAFE void UncheckedSampleBSpline(int32x Degree, int32x Dimension,
                                           real32 const *ti, real32 const *pi,
                                           real32 t, real32 *Result);
EXPAPI GS_SAFE void UncheckedSampleBSplineN(int32x Degree, int32x Dimension,
                                            real32 const *ti, real32 const *pi,
                                            real32 t, real32 *Result);

#if !defined(GRANNY_BSPLINE_INLINES_H)
#include "granny_bspline_inlines.h"
#endif

END_GRANNY_NAMESPACE;

#include "header_postfix.h"
#define GRANNY_BSPLINE_H
#endif
