- Main Page
- Related Pages
- Data Structures
- Files
- Examples

- File List

# /home/v/Kate/WORK_TREES/kate-sorceress-backup/v/src/kate/src/kate_motion.c

    00001 /* Copyright (C) 2008 Vincent Penquerc'h.
    00002    This file is part of the Kate codec library.
    00003    Written by Vincent Penquerc'h.
    00004
    00005    Use, distribution and reproduction of this library is governed
    00006    by a BSD style source license included with this source in the
    00007    file 'COPYING'. Please read these terms before distributing. */
    00008
    00009
    00010 #define KATE_INTERNAL
    00011 #include "kate_internal.h"
    00012
    00013 #ifdef HAVE_STDLIB_H
    00014 #include <stdlib.h>
    00015 #endif
    00016 #include "kate/kate.h"
    00017
    00018 static kate_float kate_catmull_rom(kate_float t,const kate_float *pts,int k0,int k1,int k2,int k3)
    00019 {
    00020   const kate_float t2=t*t,t3=t2*t;
    00021
    00022   return (
    00023     (2*pts[k1*2])
    00024     + t * (pts[k2*2]-pts[k0*2])
    00025     + t2 * (-pts[k3*2]+4*pts[k2*2]-5*pts[k1*2]+2*pts[k0*2])
    00026     + t3 * (pts[k3*2]-3*pts[k2*2]+3*pts[k1*2]-pts[k0*2])
    00027   )/2;
    00028 }
    00029
    00030 static kate_float kate_bezier_cubic(kate_float t,const kate_float *pts)
    00031 {
    00032   const kate_float t2=t*t,t3=t2*t,it=1-t,it2=it*it,it3=it2*it;
    00033
    00034   return it3*pts[0*2]
    00035          +3*t*it2*pts[1*2]
    00036          +3*t2*it*pts[2*2]
    00037          +t3*pts[3*2];
    00038 }
    00039
    00040 static kate_float kate_bspline(kate_float t,const kate_float *pts,int k0,int k1,int k2,int k3)
    00041 {
    00042   const kate_float t2=t*t,t3=t2*t,it=1-t,it2=it*it,it3=it2*it;
    00043
    00044   return (
    00045            it3*pts[k0*2]
    00046            +(3*t3-6*t2+4)*pts[k1*2]
    00047            +(-3*t3+3*t2+3*t+1)*pts[k2*2]
    00048            +t3*pts[k3*2]
    00049          )/6;
    00050 }
    00051
    00063 int kate_curve_get_point(const kate_curve *kc,kate_float t,kate_float *x,kate_float *y)
    00064 {
    00065   int nsegs,n;
    00066   kate_float T,t0,t1;
    00067
    00068   if (!kc) return KATE_E_INVALID_PARAMETER;
    00069   if (t<(kate_float)-0.001 || t>(kate_float)1.001) return KATE_E_INVALID_PARAMETER;
    00070   if (t<0) t=0;
    00071   if (t>1) t=1;
    00072   /* x and y may be NULL */
    00073
    00074   switch (kc->type) {
    00075     case kate_curve_none:
    00076       /* the motion can be discontinuous */
    00077       return 1;
    00078
    00079     case kate_curve_static:
    00080       if (x) *x=kc->pts[0];
    00081       if (y) *y=kc->pts[1];
    00082       return 0;
    00083
    00084     case kate_curve_linear:
    00085       /* find the segment we're on */
    00086       nsegs=kc->npts-1;
    00087       if (nsegs<1) return KATE_E_INIT;
    00088       n=t*nsegs;
    00089       /* ensure it doesn't overflow */
    00090       if (n<0) n=0;
    00091       if (n>=nsegs) n=nsegs-1;
    00092       /* get a 0-1 t on this segment */
    00093       t0=n/(kate_float)nsegs;
    00094       t1=(n+1)/(kate_float)nsegs;
    00095       T=(t-t0)/(t1-t0);
    00096       if (x) *x=T*kc->pts[(n+1)*2+0]+(1-T)*kc->pts[n*2+0];
    00097       if (y) *y=T*kc->pts[(n+1)*2+1]+(1-T)*kc->pts[n*2+1];
    00098       return 0;
    00099
    00100     case kate_curve_catmull_rom_spline:
    00101       /* find the segment we're on */
    00102       nsegs=kc->npts-1; /* one segment less than points */
    00103       if (nsegs<1) return KATE_E_INIT;
    00104       n=t*nsegs;
    00105       /* ensure it doesn't overflow */
    00106       if (n<0) n=0;
    00107       if (n>=nsegs) n=nsegs-1;
    00108       /* get a 0-1 t on this segment */
    00109       t0=n/(kate_float)nsegs;
    00110       t1=(n+1)/(kate_float)nsegs;
    00111       T=(t-t0)/(t1-t0);
    00112       {
    00113         int k0=n-1;
    00114         int k1=n;
    00115         int k2=n+1;
    00116         int k3=n+2;
    00117         if (n==0) k0=n;
    00118         if (n==nsegs-1) k3=n+1;
    00119         if (x) *x=kate_catmull_rom(T,kc->pts,k0,k1,k2,k3);
    00120         if (y) *y=kate_catmull_rom(T,kc->pts+1,k0,k1,k2,k3);
    00121       }
    00122       return 0;
    00123
    00124     case kate_curve_bezier_cubic_spline:
    00125       /* find the segment we're on */
    00126       if (kc->npts<4) return KATE_E_INIT;
    00127       if ((kc->npts-1)%3) return KATE_E_INIT;
    00128       nsegs=(kc->npts-1)/3; /* 4 control points per segment, with one shared */
    00129       n=t*nsegs;
    00130       /* ensure it doesn't overflow */
    00131       if (n<0) n=0;
    00132       if (n>=nsegs) n=nsegs-1;
    00133       /* get a 0-1 t on this segment */
    00134       t0=n/(kate_float)nsegs;
    00135       t1=(n+1)/(kate_float)nsegs;
    00136       T=(t-t0)/(t1-t0);
    00137       if (x) *x=kate_bezier_cubic(T,kc->pts+2*n*3);
    00138       if (y) *y=kate_bezier_cubic(T,kc->pts+2*n*3+1);
    00139       return 0;
    00140
    00141     case kate_curve_bspline:
    00142       if (kc->npts<1) return KATE_E_INIT;
    00143       /* find the segment we're on */
    00144       nsegs=kc->npts+3; /* more segments than points, end knots are 3-repeated */
    00145       if (nsegs<1) return KATE_E_INIT;
    00146       n=t*nsegs;
    00147       /* ensure it doesn't overflow */
    00148       if (n<0) n=0;
    00149       if (n>=nsegs) n=nsegs-1;
    00150       /* get a 0-1 t on this segment */
    00151       t0=n/(kate_float)nsegs;
    00152       t1=(n+1)/(kate_float)nsegs;
    00153       T=(t-t0)/(t1-t0);
    00154       {
    00155         int k0=n-3;
    00156         int k1=k0+1;
    00157         int k2=k0+2;
    00158         int k3=k0+3;
    00159 #define clamp_knot(k) do { if (k<0) k=0; if (k>=(int)kc->npts) k=kc->npts-1; } while(0)
    00160         clamp_knot(k0);
    00161         clamp_knot(k1);
    00162         clamp_knot(k2);
    00163         clamp_knot(k3);
    00164 #undef clamp_knot
    00165         if (x) *x=kate_bspline(T,kc->pts,k0,k1,k2,k3);
    00166         if (y) *y=kate_bspline(T,kc->pts+1,k0,k1,k2,k3);
    00167       }
    00168       return 0;
    00169
    00170     default:
    00171       return KATE_E_INVALID_PARAMETER;
    00172   }
    00173 }
    00174
    00187 int kate_motion_get_point(const kate_motion *km,kate_float duration,kate_float t,kate_float *x,kate_float *y)
    00188 {
    00189   size_t n;
    00190   kate_float motion_duration;
    00191
    00192   if (!km) return KATE_E_INVALID_PARAMETER;
    00193   if (duration<0) return KATE_E_INVALID_PARAMETER;
    00194   if (t<0 || t>duration) return KATE_E_INVALID_PARAMETER;
    00195   /* x and y may be NULL */
    00196
    00197   motion_duration=0;
    00198   do {
    00199     for (n=0;n<km->ncurves;++n) {
    00200       kate_float curve_duration=km->durations[n];
    00201       if (curve_duration<0.0) curve_duration=-curve_duration*duration;
    00202       if (t<=curve_duration) {
    00203         /* TODO: div by zero possible here */
    00204         return kate_curve_get_point(km->curves[n],t/curve_duration,x,y);
    00205       }
    00206       t-=curve_duration;
    00207       motion_duration+=curve_duration;
    00208     }
    00209     /* if the motion is periodic, we loop forever */
    00210     if (km->periodic) {
    00211       /* we now know the full duration, so we can remap t into 0..duration so next loop
    00212          will hit the point */
    00213       int loops=t/motion_duration;
    00214       t-=loops*motion_duration;
    00215     }
    00216   } while (km->periodic);
    00217
    00218   /* t out of range */
    00219   return KATE_E_INVALID_PARAMETER;
    00220 }
    00221
    00232 int kate_motion_destroy(const kate_info *ki,kate_motion **motions,const int *destroy,size_t nmotions,int force)
    00233 {
    00234   size_t n,l;
    00235   kate_motion *km;
    00236
    00237   if (!ki || !motions) return KATE_E_INVALID_PARAMETER;
    00238
    00239   for (n=0;n<nmotions;++n) {
    00240     km=motions[n];
    00241     if (!km) continue; /* may have holes if referred by index */
    00242     if (destroy && !destroy[n]) continue;
    00243     if (force || kate_find_motion(ki,km)<0) {
    00244       if (km->curves) {
    00245         for (l=0;l<km->ncurves;++l) {
    00246           kate_curve *kc=km->curves[l];
    00247           if (kate_find_curve(ki,kc)<0) {
    00248             kate_free(kc->pts);
    00249             kate_free(kc);
    00250           }
    00251         }
    00252         kate_free(km->curves);
    00253       }
    00254       if (km->durations) kate_free(km->durations);
    00255       kate_free(km);
    00256     }
    00257   }
    00258   kate_free(motions);
    00259
    00260   return 0;
    00261 }
    00262