Max 5 API Reference
00001 /* 00002 * jit.fractal.fbm.c 00003 * 00004 * Copyright 2001-2005 - Cycling '74 00005 * Derek Gerstmann - derek@cycling74.com 00006 * 00007 * Functor for evaluating fractional Brownian motion (fBm) (an additive 00008 * fractal) using an arbitrary signed basis function. 00009 * 00010 */ 00011 00012 // -------------------------------------------------------------------------- 00013 00014 #include "jit.common.h" 00015 #include "jit.functor.h" 00016 #include "jit.fractal.h" 00017 00018 // -------------------------------------------------------------------------- 00019 00020 #define JIT_FRACTAL_FBM_DEFAULT_INCREMENT 1.0 00021 #define JIT_FRACTAL_FBM_DEFAULT_OCTAVES 3.0 00022 #define JIT_FRACTAL_FBM_DEFAULT_LACUNARITY 2.0345 00023 00024 // -------------------------------------------------------------------------- 00025 00026 typedef struct _jit_functor_fractal_fbm 00027 { 00028 t_jit_object ob; 00029 t_symbol *basis; 00030 t_symbol *category; 00031 long seed; 00032 long rotate; 00033 long dimcount; 00034 t_jit_functor_combined_value increment; 00035 t_jit_functor_combined_value lacunarity; 00036 t_jit_functor_combined_value octaves; 00037 t_jit_functor_combined_dynarray exponents; 00038 t_jit_functor_fractal_combined_matrix_dynarray rotations; 00039 t_jit_functor_evaluator evaluator; 00040 00041 } t_jit_functor_fractal_fbm; 00042 00043 // -------------------------------------------------------------------------- 00044 00045 t_jit_object *jit_functor_fractal_fbm_new(void); 00046 t_jit_err jit_functor_fractal_fbm_free(t_jit_functor_fractal_fbm *x); 00047 00048 t_jit_err jit_functor_fractal_fbm_alter( 00049 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00050 00051 t_jit_err jit_functor_fractal_fbm_grab( 00052 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00053 00054 t_jit_err jit_functor_fractal_fbm_category(t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00055 t_jit_err jit_functor_fractal_fbm_basis(t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00056 t_jit_err jit_functor_fractal_fbm_seed(t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00057 t_jit_err jit_functor_fractal_fbm_rotate(t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00058 t_jit_err jit_functor_fractal_fbm_octaves(t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00059 t_jit_err jit_functor_fractal_fbm_increment(t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00060 t_jit_err jit_functor_fractal_fbm_lacunarity(t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv); 00061 t_jit_err jit_functor_fractal_fbm_recalc(t_jit_functor_fractal_fbm *x); 00062 t_jit_err jit_functor_fractal_fbm_exponents_init(t_jit_functor_fractal_fbm *x); 00063 00064 long jit_functor_fractal_fbm_eval_fixed(t_jit_functor_fractal_fbm *x, long dimcount, long *vals); 00065 float jit_functor_fractal_fbm_eval_float32(t_jit_functor_fractal_fbm *x, long dimcount, float *vals); 00066 double jit_functor_fractal_fbm_eval_float64(t_jit_functor_fractal_fbm *x, long dimcount, double *vals); 00067 00068 t_class * _jit_functor_fractal_fbm_class; 00069 00070 // -------------------------------------------------------------------------- 00071 00072 t_jit_err jit_functor_fractal_fbm_init(void) 00073 { 00074 t_jit_object *attr; 00075 00076 // create functor class 00077 _jit_functor_fractal_fbm_class = jit_class_new("jit_functor_fractal_fbm", 00078 (method)jit_functor_fractal_fbm_new,(method)jit_functor_fractal_fbm_free, 00079 sizeof(t_jit_functor_fractal_fbm),0L); 00080 00081 // add attribute methods 00082 attr = jit_object_new(_jit_sym_jit_attr_offset,"category",_jit_sym_symbol,0, 00083 (method)0L,(method)jit_functor_fractal_fbm_category, 00084 calcoffset(t_jit_functor_fractal_fbm,category)); 00085 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00086 attr = jit_object_new(_jit_sym_jit_attr_offset,"basis",_jit_sym_symbol,0, 00087 (method)0L,(method)jit_functor_fractal_fbm_basis, 00088 calcoffset(t_jit_functor_fractal_fbm,basis)); 00089 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00090 attr = jit_object_new(_jit_sym_jit_attr_offset,"seed",_jit_sym_long,0, 00091 (method)0L,(method)jit_functor_fractal_fbm_seed, 00092 calcoffset(t_jit_functor_fractal_fbm,seed)); 00093 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00094 attr = jit_object_new(_jit_sym_jit_attr_offset,"rotate",_jit_sym_long,0, 00095 (method)0L,(method)jit_functor_fractal_fbm_rotate, 00096 calcoffset(t_jit_functor_fractal_fbm,rotate)); 00097 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00098 attr = jit_object_new(_jit_sym_jit_attr_offset,"increment",_jit_sym_float64,0, 00099 (method)0L,(method)jit_functor_fractal_fbm_increment, 0); 00100 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00101 attr = jit_object_new(_jit_sym_jit_attr_offset,"octaves",_jit_sym_float64,0, 00102 (method)0L,(method)jit_functor_fractal_fbm_octaves, 0); 00103 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00104 attr = jit_object_new(_jit_sym_jit_attr_offset,"lacunarity",_jit_sym_float64,0, 00105 (method)0L,(method)jit_functor_fractal_fbm_lacunarity, 0); 00106 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00107 00108 // add delegate methods 00109 attr = jit_object_new(_jit_sym_jit_attr_offset,"alter",_jit_sym_symbol,0, 00110 (method)0L,(method)jit_functor_fractal_fbm_alter,0L); 00111 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00112 attr = jit_object_new(_jit_sym_jit_attr_offset,"grab",_jit_sym_symbol,0, 00113 (method)jit_functor_fractal_fbm_grab, (method)0L, 0L); 00114 jit_class_addattr(_jit_functor_fractal_fbm_class,attr); 00115 00116 // add evaluation methods 00117 jit_class_addmethod(_jit_functor_fractal_fbm_class, 00118 (method)jit_functor_fractal_fbm_eval_fixed, "evalfixed", A_CANT, 0L); 00119 jit_class_addmethod(_jit_functor_fractal_fbm_class, 00120 (method)jit_functor_fractal_fbm_eval_float32, "evalfloat32", A_CANT, 0L); 00121 jit_class_addmethod(_jit_functor_fractal_fbm_class, 00122 (method)jit_functor_fractal_fbm_eval_float64, "evalfloat64", A_CANT, 0L); 00123 00124 // important to add last for subclassing methods 00125 jit_functor_setup_class(_jit_functor_fractal_fbm_class,"fractal","fbm"); 00126 jit_class_register(_jit_functor_fractal_fbm_class); 00127 00128 return JIT_ERR_NONE; 00129 } 00130 00131 t_jit_object *jit_functor_fractal_fbm_new(void) 00132 { 00133 t_jit_functor_fractal_fbm *x; 00134 t_atom a; 00135 00136 if (x = (t_jit_functor_fractal_fbm *)jit_object_alloc(_jit_functor_fractal_fbm_class)) { 00137 00138 // initialization 00139 x->category = gensym("noise"); 00140 x->basis = gensym("gradient"); 00141 x->rotate = FALSE; 00142 x->seed = JIT_FRACTAL_DEFAULT_SEED; 00143 x->dimcount = 2; 00144 00145 // set all data members 00146 JIT_FUNCTOR_COMBINED_VALUE_SETALL(x->increment, JIT_FRACTAL_FBM_DEFAULT_INCREMENT); 00147 JIT_FUNCTOR_COMBINED_VALUE_SETALL(x->octaves, JIT_FRACTAL_FBM_DEFAULT_OCTAVES); 00148 JIT_FUNCTOR_COMBINED_VALUE_SETALL(x->lacunarity, JIT_FRACTAL_FBM_DEFAULT_LACUNARITY); 00149 00150 x->exponents.float64 = NULL; 00151 x->exponents.float32 = NULL; 00152 x->exponents.fixed = NULL; 00153 x->exponents.count = 0; 00154 00155 x->rotations.m = NULL; 00156 x->rotations.count = 0; 00157 00158 x->evaluator.ob = NULL; 00159 x->evaluator.fm = NULL; 00160 00161 jit_functor_evaluator_init(&x->evaluator, x->category, x->basis); 00162 00163 // enable signed evaluation 00164 jit_atom_setlong(&a, 1); 00165 jit_object_method(x->evaluator.ob, gensym("sign"), 1, &a); 00166 00167 // init exponents 00168 jit_functor_fractal_exponents_init( 00169 &x->exponents, x->octaves.float64, 00170 x->increment.float64, x->lacunarity.float64); 00171 00172 jit_functor_fractal_fbm_recalc(x); 00173 } 00174 00175 return (t_jit_object *)x; 00176 } 00177 00178 t_jit_err jit_functor_fractal_fbm_free(t_jit_functor_fractal_fbm *x) 00179 { 00180 // dispose allocated mem 00181 jit_functor_combined_dynarray_destroy(&x->exponents); 00182 jit_functor_fractal_rotations_destroy(&x->rotations); 00183 00184 if(x->evaluator.ob) 00185 jit_object_free(x->evaluator.ob); 00186 x->evaluator.ob = NULL; 00187 x->evaluator.fm = NULL; 00188 00189 return JIT_ERR_NONE; 00190 } 00191 00192 t_jit_err jit_functor_fractal_fbm_alter( 00193 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00194 { 00195 t_jit_err rv = JIT_ERR_GENERIC; 00196 t_symbol *s = NULL; 00197 00198 if(!x) 00199 return rv; 00200 00201 s = jit_atom_getsym(argv); 00202 if(s && s->s_name) 00203 { 00204 rv = (t_jit_err) jit_object_method(x->evaluator.ob, s, argc-1, argv+1); 00205 } 00206 jit_functor_fractal_fbm_recalc(x); 00207 return rv; 00208 } 00209 00210 t_jit_err jit_functor_fractal_fbm_grab( 00211 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00212 { 00213 t_jit_err rv = JIT_ERR_GENERIC; 00214 t_symbol *s = NULL; 00215 char tmp[256]; 00216 00217 if(!x) 00218 return rv; 00219 00220 s = jit_atom_getsym(argv); 00221 if(s && s->s_name) 00222 { 00223 sprintf(tmp,"get%s",s->s_name); 00224 s = gensym(tmp); 00225 rv = (t_jit_err) jit_object_method(x->evaluator.ob, s, argc-1, argv+1); 00226 } 00227 00228 return rv; 00229 } 00230 00231 t_jit_err jit_functor_fractal_fbm_category( 00232 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00233 { 00234 t_jit_err err; 00235 t_symbol *v; 00236 t_atom a; 00237 00238 if (x) { 00239 v = jit_atom_getsym(argv); 00240 if (x->category != v) { 00241 x->category = v; 00242 00243 err = jit_functor_evaluator_init(&x->evaluator, x->category, x->basis); 00244 if(err) return err; 00245 00246 jit_atom_setlong(&a, 1); 00247 err = (t_jit_err) jit_object_method(x->evaluator.ob, gensym("sign"), 1, &a); 00248 if(err) 00249 jit_object_post((t_object *)x,"jit.fractal.fbm: selected evaluator may not produce an appropriate output range"); 00250 00251 jit_functor_fractal_fbm_recalc(x); 00252 } 00253 return JIT_ERR_NONE; 00254 } 00255 return JIT_ERR_INVALID_PTR; 00256 } 00257 00258 t_jit_err jit_functor_fractal_fbm_basis( 00259 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00260 { 00261 t_jit_err err; 00262 t_symbol *v; 00263 t_atom a; 00264 00265 if (x) { 00266 v = jit_atom_getsym(argv); 00267 if (x->basis != v) { 00268 x->basis = v; 00269 00270 err = jit_functor_evaluator_init(&x->evaluator, x->category, x->basis); 00271 if(err) return err; 00272 00273 jit_atom_setlong(&a, 1); 00274 err = (t_jit_err) jit_object_method(x->evaluator.ob, gensym("sign"), 1, &a); 00275 if(err) 00276 jit_object_post((t_object *)x,"jit.fractal.fbm: selected evaluator may not produce an appropriate output range"); 00277 00278 jit_functor_fractal_fbm_recalc(x); 00279 } 00280 return JIT_ERR_NONE; 00281 } 00282 return JIT_ERR_INVALID_PTR; 00283 } 00284 00285 t_jit_err jit_functor_fractal_fbm_rotate( 00286 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00287 { 00288 long v; 00289 00290 if (x) { 00291 v = jit_atom_getlong(argv); 00292 if (x->rotate != v) { 00293 x->rotate = (v > 0) ? TRUE : FALSE; 00294 jit_functor_fractal_rotations_init(&x->rotations, x->octaves.float64, x->dimcount, x->seed); 00295 jit_functor_fractal_fbm_recalc(x); 00296 } 00297 return JIT_ERR_NONE; 00298 } 00299 return JIT_ERR_INVALID_PTR; 00300 } 00301 00302 t_jit_err jit_functor_fractal_fbm_seed( 00303 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00304 { 00305 long v; 00306 00307 if (x) { 00308 v = jit_atom_getlong(argv); 00309 if (x->seed != v) { 00310 x->seed = v; 00311 jit_functor_fractal_rotations_init(&x->rotations, x->octaves.float64, x->dimcount, x->seed); 00312 jit_functor_fractal_fbm_recalc(x); 00313 } 00314 return JIT_ERR_NONE; 00315 } 00316 return JIT_ERR_INVALID_PTR; 00317 } 00318 00319 t_jit_err jit_functor_fractal_fbm_increment( 00320 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00321 { 00322 double v; 00323 00324 if (x) { 00325 v = jit_atom_getfloat(argv); 00326 if (x->increment.float64 != v) { 00327 00328 // copy and convert 00329 JIT_FUNCTOR_COMBINED_VALUE_SETALL(x->increment, v); 00330 00331 // init exponents 00332 jit_functor_fractal_exponents_init( 00333 &x->exponents, x->octaves.float64, 00334 x->increment.float64, x->lacunarity.float64); 00335 00336 jit_functor_fractal_fbm_recalc(x); 00337 } 00338 return JIT_ERR_NONE; 00339 } 00340 return JIT_ERR_INVALID_PTR; 00341 } 00342 00343 00344 t_jit_err jit_functor_fractal_fbm_octaves( 00345 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00346 { 00347 double v; 00348 00349 if (x) { 00350 v = jit_atom_getfloat(argv); 00351 if (x->octaves.float64 != v && v > 0.0) { 00352 00353 // copy and convert 00354 JIT_FUNCTOR_COMBINED_VALUE_SETALL(x->octaves, v); 00355 00356 // init exponents 00357 jit_functor_fractal_exponents_init( 00358 &x->exponents, x->octaves.float64, 00359 x->increment.float64, x->lacunarity.float64); 00360 00361 jit_functor_fractal_fbm_recalc(x); 00362 } 00363 return JIT_ERR_NONE; 00364 } 00365 return JIT_ERR_INVALID_PTR; 00366 } 00367 00368 t_jit_err jit_functor_fractal_fbm_lacunarity( 00369 t_jit_functor_fractal_fbm *x, void *attr, long argc, t_atom *argv) 00370 { 00371 double v; 00372 00373 if (x) { 00374 v = jit_atom_getfloat(argv); 00375 if (x->lacunarity.float64 != v) { 00376 00377 // copy and convert 00378 JIT_FUNCTOR_COMBINED_VALUE_SETALL(x->lacunarity, v); 00379 00380 // init exponents 00381 jit_functor_fractal_exponents_init( 00382 &x->exponents, x->octaves.float64, 00383 x->increment.float64, x->lacunarity.float64); 00384 00385 jit_functor_fractal_fbm_recalc(x); 00386 } 00387 return JIT_ERR_NONE; 00388 } 00389 return JIT_ERR_INVALID_PTR; 00390 } 00391 00392 t_jit_err jit_functor_fractal_fbm_recalc( 00393 t_jit_functor_fractal_fbm *x) 00394 { 00395 // calculate intermediary values for efficiency 00396 return JIT_ERR_NONE; 00397 } 00398 00399 // -------------------------------------------------------------------------- 00400 // vector evaluation functions 00401 // -------------------------------------------------------------------------- 00402 long jit_functor_fractal_fbm_eval_fixed( 00403 t_jit_functor_fractal_fbm *x, long dimcount, long *vals) 00404 { 00405 /* TODO! */ 00406 return jit_functor_eval_fixed_with_float32((t_jit_object *)x,dimcount,vals, 00407 (t_jit_functor_float32_sig)jit_functor_fractal_fbm_eval_float32); 00408 } 00409 00410 float jit_functor_fractal_fbm_eval_float32( 00411 t_jit_functor_fractal_fbm *x, long dimcount, float *vals) 00412 { 00413 long i, j, k; 00414 long count = (long)x->octaves.float32; 00415 float pos[JIT_MATRIX_MAX_DIMCOUNT]; 00416 float rot[JIT_MATRIX_MAX_DIMCOUNT]; 00417 00418 float basis; 00419 float value; 00420 float rem; 00421 00422 // safety 00423 if(!x->evaluator.ob || !x->evaluator.fm || !x->exponents.float32) 00424 return 0.0f; 00425 00426 // reinit rotations if dimcount has changed 00427 if(dimcount != x->dimcount && x->rotate) { 00428 x->dimcount = dimcount; 00429 jit_functor_fractal_rotations_init(&x->rotations, x->octaves.float64, x->dimcount, x->seed); 00430 } 00431 00432 // make a local copy of the position 00433 for( i = 0; i < dimcount; i++) 00434 pos[i] = vals[i]; 00435 00436 value = 0.0f; 00437 for ( i = 0; i < count; i++ ) 00438 { 00439 // evaluate the basis function to create the spectrum 00440 basis = x->evaluator.fm->evalfloat32(x->evaluator.ob, dimcount, pos ); 00441 value += basis * x->exponents.float32[i]; 00442 00443 // multipy in the lacunarity to create the gaps between octaves 00444 for( j = 0; j < dimcount; j++ ) 00445 pos[j] *= x->lacunarity.float32; 00446 00447 // apply rotation to reduce alignment artifacts 00448 if(x->rotate) { 00449 for( j = 0; j < dimcount; j++ ) { 00450 rot[j] = 0; 00451 for( k = 0; k < dimcount; k++ ) { 00452 rot[j] += x->rotations.m[i].float32[j][k] * pos[k]; 00453 } 00454 } 00455 for( j = 0; j < dimcount; j++ ) 00456 pos[j] = rot[j]; 00457 } 00458 } 00459 00460 // take care of remainder in octaves using i from above 00461 rem = x->octaves.float32 - count; 00462 if ( rem ) 00463 { 00464 basis = x->evaluator.fm->evalfloat32(x->evaluator.ob, dimcount, pos ); 00465 value += rem * basis * x->exponents.float32[i]; 00466 } 00467 00468 return value; 00469 } 00470 00471 double jit_functor_fractal_fbm_eval_float64( 00472 t_jit_functor_fractal_fbm *x, long dimcount, double *vals) 00473 { 00474 long i, j, k; 00475 long count = (long)x->octaves.float64; 00476 double pos[JIT_MATRIX_MAX_DIMCOUNT]; 00477 double rot[JIT_MATRIX_MAX_DIMCOUNT]; 00478 00479 double basis; 00480 double value; 00481 double rem; 00482 00483 // safety 00484 if(!x->evaluator.ob || !x->evaluator.fm || !x->exponents.float64) 00485 return 0.0f; 00486 00487 // reinit rotations if dimcount has changed 00488 if(dimcount != x->dimcount && x->rotate) { 00489 x->dimcount = dimcount; 00490 jit_functor_fractal_rotations_init(&x->rotations, x->octaves.float64, x->dimcount, x->seed); 00491 } 00492 00493 // make a local copy of the position 00494 for( i = 0; i < dimcount; i++) 00495 pos[i] = vals[i]; 00496 00497 value = 0.0; 00498 for ( i = 0; i < count; i++ ) 00499 { 00500 // evaluate the basis function to create the spectrum 00501 basis = x->evaluator.fm->evalfloat64(x->evaluator.ob, dimcount, pos ); 00502 value += basis * x->exponents.float64[i]; 00503 00504 // multipy in the lacunarity to create the gaps between octaves 00505 for( j = 0; j < dimcount; j++ ) 00506 pos[j] *= x->lacunarity.float64; 00507 00508 // apply rotation to reduce alignment artifacts 00509 if(x->rotate) { 00510 for( j = 0; j < dimcount; j++ ) { 00511 rot[j] = 0; 00512 for( k = 0; k < dimcount; k++ ) { 00513 rot[j] += x->rotations.m[i].float64[j][k] * pos[k]; 00514 } 00515 } 00516 for( j = 0; j < dimcount; j++ ) 00517 pos[j] = rot[j]; 00518 } 00519 } 00520 00521 // take care of remainder in octaves using i from above 00522 rem = x->octaves.float64 - count; 00523 if ( rem ) 00524 { 00525 basis = x->evaluator.fm->evalfloat64(x->evaluator.ob, dimcount, pos ); 00526 value += rem * basis * x->exponents.float64[i]; 00527 } 00528 00529 return value; 00530 } 00531 // --------------------------------------------------------------------------
Copyright © 2008, Cycling '74