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