00001 
00002 
00003 
00004 
00005 
00006 
00007 
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   
00073 
00074   switch (kc->type) {
00075     case kate_curve_none:
00076       
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       
00086       nsegs=kc->npts-1;
00087       if (nsegs<1) return KATE_E_INIT;
00088       n=t*nsegs;
00089       
00090       if (n<0) n=0;
00091       if (n>=nsegs) n=nsegs-1;
00092       
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       
00102       nsegs=kc->npts-1; 
00103       if (nsegs<1) return KATE_E_INIT;
00104       n=t*nsegs;
00105       
00106       if (n<0) n=0;
00107       if (n>=nsegs) n=nsegs-1;
00108       
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       
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; 
00129       n=t*nsegs;
00130       
00131       if (n<0) n=0;
00132       if (n>=nsegs) n=nsegs-1;
00133       
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       
00144       nsegs=kc->npts+3; 
00145       if (nsegs<1) return KATE_E_INIT;
00146       n=t*nsegs;
00147       
00148       if (n<0) n=0;
00149       if (n>=nsegs) n=nsegs-1;
00150       
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   
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         
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     
00210     if (km->periodic) {
00211       
00212 
00213       int loops=t/motion_duration;
00214       t-=loops*motion_duration;
00215     }
00216   } while (km->periodic);
00217 
00218   
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; 
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