Max 5 API Reference
00001 /* 00002 * Copyright 2001-2005 - Cycling '74 00003 * Derek Gerstmann - derek@cycling74.com 00004 * 00005 * Cubic spline evaluation and utility methods 00006 * 00007 */ 00008 00009 #include "jit.common.h" 00010 #include "jit.cubicspline.h" 00011 #include "jit.fixmath.h" 00012 00013 // -------------------------------------------------------------------------- 00014 00015 static long g_jit_cubicspline_is_initialized = FALSE; 00016 00017 // -------------------------------------------------------------------------- 00018 00019 t_symbol *ps_jit_cubicspline_basisname_bezier; 00020 t_jit_cubicspline_basismatrix_float64 g_cubicspline_basismatrix_bezier = { 00021 { -1.0, 3.0, -3.0, 1.0}, 00022 { 3.0, -6.0, 3.0, 0.0}, 00023 { -3.0, 3.0, 0.0, 0.0}, 00024 { 1.0, 0.0, 0.0, 0.0} 00025 }; 00026 00027 t_symbol *ps_jit_cubicspline_basisname_bspline; 00028 t_jit_cubicspline_basismatrix_float64 g_cubicspline_basismatrix_bspline = { 00029 { -1.0/6.0, 0.5, -0.5, 1.0/6.0}, 00030 { 0.5, -1.0, 0.5, 0.0}, 00031 { -0.5, 0.0, 0.5, 0.0}, 00032 { 1.0/6.0, 2.0/3.0, 1.0/6.0, 0.0} 00033 }; 00034 00035 t_symbol *ps_jit_cubicspline_basisname_catmullrom; 00036 t_jit_cubicspline_basismatrix_float64 g_cubicspline_basismatrix_catmullrom = { 00037 { -0.5, 1.5, -1.5, 0.5}, 00038 { 1.0, -2.5, 2.0, -0.5}, 00039 { -0.5, 0.0, 0.5, 0.0}, 00040 { 0.0, 1.0, 0.0, 0.0} 00041 }; 00042 00043 t_symbol *ps_jit_cubicspline_basisname_hermite; 00044 t_jit_cubicspline_basismatrix_float64 g_cubicspline_basismatrix_hermite = { 00045 { 2.0, -2.0, 1.0, 1.0 }, 00046 { -3.0, 3.0, -2.0, -1.0 }, 00047 { 0.0, 0.0, 1.0, 0.0 }, 00048 { 1.0, 0.0, 0.0, 0.0 } 00049 }; 00050 00051 t_symbol *ps_jit_cubicspline_basisname_power; 00052 t_jit_cubicspline_basismatrix_float64 g_cubicspline_basismatrix_power = { 00053 { 1.0, 0.0, 0.0, 0.0}, 00054 { 0.0, 1.0, 0.0, 0.0}, 00055 { 0.0, 0.0, 1.0, 0.0}, 00056 { 0.0, 0.0, 0.0, 1.0} 00057 }; 00058 00059 // -------------------------------------------------------------------------- 00060 00061 t_jit_err jit_cubicspline_init() 00062 { 00063 // generate symbols 00064 ps_jit_cubicspline_basisname_bezier = gensym("bezier"); 00065 ps_jit_cubicspline_basisname_bspline = gensym("bspline"); 00066 ps_jit_cubicspline_basisname_catmullrom = gensym("catmullrom"); 00067 ps_jit_cubicspline_basisname_hermite = gensym("hermite"); 00068 ps_jit_cubicspline_basisname_power = gensym("power"); 00069 g_jit_cubicspline_is_initialized = TRUE; 00070 return JIT_ERR_NONE; 00071 } 00072 00073 // -------------------------------------------------------------------------- 00074 00075 t_jit_err jit_cubicspline_fillbasis_fixed( 00076 t_symbol *name, t_jit_cubicspline_basismatrix_fixed *matrix, 00077 long *stepcount) 00078 { 00079 long i, j; 00080 00081 if(!g_jit_cubicspline_is_initialized) 00082 jit_cubicspline_init(); 00083 00084 if(name && matrix && stepcount) 00085 { 00086 if(name == ps_jit_cubicspline_basisname_bezier) 00087 { 00088 *stepcount = 3; 00089 for(i = 0; i < 4; i++) 00090 for(j = 0; j < 4; j++) 00091 (*matrix)[i][j] = DoubleToFixed(g_cubicspline_basismatrix_bezier[i][j]); 00092 } 00093 else if(name == ps_jit_cubicspline_basisname_bspline) 00094 { 00095 *stepcount = 1; 00096 for(i = 0; i < 4; i++) 00097 for(j = 0; j < 4; j++) 00098 (*matrix)[i][j] = DoubleToFixed(g_cubicspline_basismatrix_bspline[i][j]); 00099 } 00100 else if(name == ps_jit_cubicspline_basisname_catmullrom) 00101 { 00102 *stepcount = 1; 00103 for(i = 0; i < 4; i++) 00104 for(j = 0; j < 4; j++) 00105 (*matrix)[i][j] = DoubleToFixed(g_cubicspline_basismatrix_catmullrom[i][j]); 00106 } 00107 else if(name == ps_jit_cubicspline_basisname_hermite) 00108 { 00109 *stepcount = 2; 00110 for(i = 0; i < 4; i++) 00111 for(j = 0; j < 4; j++) 00112 (*matrix)[i][j] = DoubleToFixed(g_cubicspline_basismatrix_hermite[i][j]); 00113 } 00114 else if(name == ps_jit_cubicspline_basisname_power) 00115 { 00116 *stepcount = 4; 00117 for(i = 0; i < 4; i++) 00118 for(j = 0; j < 4; j++) 00119 (*matrix)[i][j] = DoubleToFixed(g_cubicspline_basismatrix_power[i][j]); 00120 } 00121 else 00122 { 00123 // invalid basis name 00124 return JIT_ERR_GENERIC; 00125 } 00126 00127 // no error 00128 return JIT_ERR_NONE; 00129 } 00130 00131 // invalid pointer or index 00132 return JIT_ERR_GENERIC; 00133 } 00134 00135 t_jit_err jit_cubicspline_fillbasis_float32( 00136 t_symbol *name, t_jit_cubicspline_basismatrix_float32 *matrix, 00137 long *stepcount) 00138 { 00139 long i, j; 00140 00141 if(!g_jit_cubicspline_is_initialized) 00142 jit_cubicspline_init(); 00143 00144 if(name && matrix && stepcount) 00145 { 00146 if(name == ps_jit_cubicspline_basisname_bezier) 00147 { 00148 *stepcount = 3; 00149 for(i = 0; i < 4; i++) 00150 for(j = 0; j < 4; j++) 00151 (*matrix)[i][j] = (float)g_cubicspline_basismatrix_bezier[i][j]; 00152 } 00153 else if(name == ps_jit_cubicspline_basisname_bspline) 00154 { 00155 *stepcount = 1; 00156 for(i = 0; i < 4; i++) 00157 for(j = 0; j < 4; j++) 00158 (*matrix)[i][j] = (float)g_cubicspline_basismatrix_bspline[i][j]; 00159 } 00160 else if(name == ps_jit_cubicspline_basisname_catmullrom) 00161 { 00162 *stepcount = 1; 00163 for(i = 0; i < 4; i++) 00164 for(j = 0; j < 4; j++) 00165 (*matrix)[i][j] = (float)g_cubicspline_basismatrix_catmullrom[i][j]; 00166 } 00167 else if(name == ps_jit_cubicspline_basisname_hermite) 00168 { 00169 *stepcount = 2; 00170 for(i = 0; i < 4; i++) 00171 for(j = 0; j < 4; j++) 00172 (*matrix)[i][j] = (float)g_cubicspline_basismatrix_hermite[i][j]; 00173 } 00174 else if(name == ps_jit_cubicspline_basisname_power) 00175 { 00176 *stepcount = 4; 00177 for(i = 0; i < 4; i++) 00178 for(j = 0; j < 4; j++) 00179 (*matrix)[i][j] = (float)g_cubicspline_basismatrix_power[i][j]; 00180 } 00181 else 00182 { 00183 // invalid basis name 00184 return JIT_ERR_GENERIC; 00185 } 00186 00187 // no error 00188 return JIT_ERR_NONE; 00189 } 00190 00191 // invalid pointer or index 00192 return JIT_ERR_GENERIC; 00193 } 00194 00195 t_jit_err jit_cubicspline_fillbasis_float64( 00196 t_symbol *name, t_jit_cubicspline_basismatrix_float64 *matrix, 00197 long *stepcount) 00198 { 00199 long i, j; 00200 00201 if(!g_jit_cubicspline_is_initialized) 00202 jit_cubicspline_init(); 00203 00204 if(name && matrix && stepcount) 00205 { 00206 if(name == ps_jit_cubicspline_basisname_bezier) 00207 { 00208 *stepcount = 3; 00209 for(i = 0; i < 4; i++) 00210 for(j = 0; j < 4; j++) 00211 (*matrix)[i][j] = (double)g_cubicspline_basismatrix_bezier[i][j]; 00212 } 00213 else if(name == ps_jit_cubicspline_basisname_bspline) 00214 { 00215 *stepcount = 1; 00216 for(i = 0; i < 4; i++) 00217 for(j = 0; j < 4; j++) 00218 (*matrix)[i][j] = (double)g_cubicspline_basismatrix_bspline[i][j]; 00219 } 00220 else if(name == ps_jit_cubicspline_basisname_catmullrom) 00221 { 00222 *stepcount = 1; 00223 for(i = 0; i < 4; i++) 00224 for(j = 0; j < 4; j++) 00225 (*matrix)[i][j] = (double)g_cubicspline_basismatrix_catmullrom[i][j]; 00226 } 00227 else if(name == ps_jit_cubicspline_basisname_hermite) 00228 { 00229 *stepcount = 2; 00230 for(i = 0; i < 4; i++) 00231 for(j = 0; j < 4; j++) 00232 (*matrix)[i][j] = (double)g_cubicspline_basismatrix_hermite[i][j]; 00233 } 00234 else if(name == ps_jit_cubicspline_basisname_power) 00235 { 00236 *stepcount = 4; 00237 for(i = 0; i < 4; i++) 00238 for(j = 0; j < 4; j++) 00239 (*matrix)[i][j] = (double)g_cubicspline_basismatrix_power[i][j]; 00240 } 00241 else 00242 { 00243 // invalid basis name 00244 return JIT_ERR_GENERIC; 00245 } 00246 00247 // no error 00248 return JIT_ERR_NONE; 00249 } 00250 00251 // invalid pointer or index 00252 return JIT_ERR_GENERIC; 00253 } 00254 00255 long jit_cubicspline_general_eval_fixed( 00256 long val, long stepcount, long knotcount, long *knots, 00257 t_jit_cubicspline_basismatrix_fixed matrix) 00258 { 00259 long k0, k1, k2, k3; 00260 long c0, c1, c2, c3; 00261 long a, b, c; 00262 long t, u; 00263 00264 long span = 0; 00265 long spancount = 0; 00266 long index = 0; 00267 00268 // safety 00269 if(!knots || stepcount < 1) 00270 return FloatToFixed(0.0f); 00271 00272 // find the appropriate 4-point span of the spline to eval 00273 t = val; 00274 spancount = ((knotcount - 4) / stepcount) + 1; 00275 00276 // sanity 00277 if(spancount < 1) 00278 return FloatToFixed(0.0f); 00279 00280 u = FloatToFixed((float)spancount * FixedToFloat(t)); 00281 span = (long)FixedToFloat(u); 00282 00283 t = u - span; 00284 index = span * stepcount; 00285 00286 // get the control points 00287 k0 = knots[ index + 0 ]; 00288 k1 = knots[ index + 1 ]; 00289 k2 = knots[ index + 2 ]; 00290 k3 = knots[ index + 3 ]; 00291 00292 // evaluate using horners rule 00293 c0 = FixMul3(matrix[3][0], k0) + FixMul3(matrix[3][1], k1) 00294 + FixMul3(matrix[3][2], k2) + FixMul3(matrix[3][3], k3); 00295 00296 c1 = FixMul3(matrix[2][0], k0) + FixMul3(matrix[2][1], k1) 00297 + FixMul3(matrix[2][2], k2) + FixMul3(matrix[2][3], k3); 00298 00299 c2 = FixMul3(matrix[1][0], k0) + FixMul3(matrix[1][1], k1) 00300 + FixMul3(matrix[1][2], k2) + FixMul3(matrix[1][3], k3); 00301 00302 c3 = FixMul3(matrix[0][0], k0) + FixMul3(matrix[0][1], k1) 00303 + FixMul3(matrix[0][2], k2) + FixMul3(matrix[0][3], k3); 00304 00305 a = FixMul(c3, val) + c2; 00306 b = FixMul(a, val) + c1; 00307 c = FixMul(b, val) + c0; 00308 return c; 00309 } 00310 00311 float jit_cubicspline_general_eval_float32( 00312 float val, long stepcount, long knotcount, float *knots, 00313 t_jit_cubicspline_basismatrix_float32 matrix) 00314 { 00315 float k0, k1, k2, k3; 00316 float c0, c1, c2, c3; 00317 float t, u; 00318 00319 long span = 0; 00320 long spancount = 0; 00321 long index = 0; 00322 00323 // safety 00324 if(!knots || stepcount < 1) 00325 return 0.0f; 00326 00327 // find the appropriate 4-point span of the spline to eval 00328 t = val; 00329 spancount = ((knotcount - 4) / stepcount) + 1; 00330 00331 // sanity 00332 if(spancount < 1) 00333 return 0.0f; 00334 00335 u = (float)spancount * t; 00336 span = (long)u; 00337 00338 t = u - span; 00339 index = span * stepcount; 00340 00341 // get the control points 00342 k0 = knots[ index + 0 ]; 00343 k1 = knots[ index + 1 ]; 00344 k2 = knots[ index + 2 ]; 00345 k3 = knots[ index + 3 ]; 00346 00347 // evaluate using horners rule 00348 c0 = matrix[3][0] * k0 + matrix[3][1] * k1 00349 + matrix[3][2] * k2 + matrix[3][3] * k3; 00350 00351 c1 = matrix[2][0] * k0 + matrix[2][1] * k1 00352 + matrix[2][2] * k2 + matrix[2][3] * k3; 00353 00354 c2 = matrix[1][0] * k0 + matrix[1][1] * k1 00355 + matrix[1][2] * k2 + matrix[1][3] * k3; 00356 00357 c3 = matrix[0][0] * k0 + matrix[0][1] * k1 00358 + matrix[0][2] * k2 + matrix[0][3] * k3; 00359 00360 return ( ( c3 * t + c2 ) * t + c1 ) * t + c0; 00361 } 00362 00363 double jit_cubicspline_general_eval_float64( 00364 double val, long stepcount, long knotcount, double *knots, 00365 t_jit_cubicspline_basismatrix_float64 matrix) 00366 { 00367 double k0, k1, k2, k3; 00368 double c0, c1, c2, c3; 00369 double t, u; 00370 00371 long span = 0; 00372 long spancount = 0; 00373 long index = 0; 00374 00375 // safety 00376 if(!knots || stepcount < 1) 00377 return 0.0f; 00378 00379 // find the appropriate 4-point span of the spline to eval 00380 t = val; 00381 spancount = ((knotcount - 4) / stepcount) + 1; 00382 00383 // sanity 00384 if(spancount < 1) 00385 return 0.0; 00386 00387 u = (float)spancount * t; 00388 span = (long)u; 00389 00390 t = u - span; 00391 index = span * stepcount; 00392 00393 // get the control points 00394 k0 = knots[ index + 0 ]; 00395 k1 = knots[ index + 1 ]; 00396 k2 = knots[ index + 2 ]; 00397 k3 = knots[ index + 3 ]; 00398 00399 // evaluate using horners rule 00400 c0 = matrix[3][0] * k0 + matrix[3][1] * k1 00401 + matrix[3][2] * k2 + matrix[3][3] * k3; 00402 00403 c1 = matrix[2][0] * k0 + matrix[2][1] * k1 00404 + matrix[2][2] * k2 + matrix[2][3] * k3; 00405 00406 c2 = matrix[1][0] * k0 + matrix[1][1] * k1 00407 + matrix[1][2] * k2 + matrix[1][3] * k3; 00408 00409 c3 = matrix[0][0] * k0 + matrix[0][1] * k1 00410 + matrix[0][2] * k2 + matrix[0][3] * k3; 00411 00412 return ( ( c3 * t + c2 ) * t + c1 ) * t + c0; 00413 }
Copyright © 2008, Cycling '74