/* -------------------------- pmpd ---------------------------------------- pmpd = physical modeling for pure data Written by Cyrille Henry (cyrille.henry@la-kitchen.fr) Get sources at http://drpichon.free.fr/pure-data/physical-modeling/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Based on PureData by Miller Puckette and others. ---------------------------------------------------------------------------- */ #ifndef VERSION #define VERSION "0.07" #endif #include "m_pd.h" #include "stdio.h" #ifndef __DATE__ #define __DATE__ "" #endif #define nb_max_link 2000 #define nb_max_mass 2000 #define nb_max_out 200 #define nb_max_in 200 #define nb_max_outlet 20 #define nb_max_inlet 20 // hard-coded on the methods definition #define max(a,b) ( ((a) > (b)) ? (a) : (b) ) #define min(a,b) ( ((a) < (b)) ? (a) : (b) ) /* #include "masse.c" #include "lia.c" #include "masse2D.c" #include "lia2D.c" #include "masse3D.c" #include "lia3D.c" #include "iAmbient2D.c" #include "iLine2D.c" #include "iSeg2D.c" #include "iCircle2D.c" #include "tSquare2D.c" #include "tLine2D.c" #include "tSeg2D.c" #include "tCircle2D.c" #include "tLia2D.c" #include "iAmbient3D.c" #include "iSphere3D.c" #include "iPlane3D.c" #include "iCircle3D.c" #include "iCylinder3D.c" #include "tCube3D.c" #include "tSphere3D.c" #include "tPlane3D.c" #include "tCircle3D.c" #include "tCylinder3D.c" #include "tLia3D.c" #include "pmpd~.c" */ static t_class *pmpd_class; typedef struct _mass { t_int Id; t_float invM; t_float speedX; t_float posX; t_float forceX; } foo; typedef struct _link { t_int Id; struct _mass *mass1; struct _mass *mass2; t_float Ke, K1, D1, K2, D2; } foo1 ; typedef struct _out { // TODO ajouter un type pour diferencier les outlets en forces et celles en position t_int Id; t_int nbr_outlet; struct _mass *mass1; t_float influence; } foo2; typedef struct _in { // TODO ajouter un type pour diferencier les inlets en forces et celles en position t_int Id; t_int nbr_inlet; struct _mass *mass1; t_float influence; } foo3; typedef struct _pmpd { t_object x_obj; struct _link link[nb_max_link]; struct _mass mass[nb_max_mass]; struct _out out[nb_max_out]; struct _in in[nb_max_in]; t_float outlet[nb_max_outlet]; t_outlet *taboutlet[nb_max_outlet]; t_float inlet[nb_max_inlet]; int nb_link, nb_mass, nb_outlet, nb_inlet, nb_in, nb_out; } t_pmpd; void pmpd_bang(t_pmpd *x) /////////////////////////////////////////////////////////////////////////////////// // this part is doing all the job! { t_float F; t_int i; struct _mass mass_1, mass_2; for (i=0; inb_in; i++) // compute input { x->in[i].mass1->forceX += x->in[i].influence * x->inlet[x->in[i].nbr_inlet]; } for (i=0; inb_inlet; i++) // clear inlet[i] { x->inlet[i]=0; } for (i=0; inb_link; i++) // comput link forces { F = x->link[i].K1 * ( x->link[i].mass1->posX - x->link[i].mass2->posX ) ; F += x->link[i].D1 * ( x->link[i].mass1->speedX - x->link[i].mass2->speedX) ; x->link[i].mass1->forceX -= F; x->link[i].mass2->forceX += F; } for (i=1; inb_mass; i++) // compute new masses position if (x->mass[i].Id >0) // only if Id >0 { x->mass[i].speedX += x->mass[i].forceX * x->mass[i].invM; x->mass[i].forceX = 0; x->mass[i].posX += x->mass[i].speedX ; } for (i=0; inb_out; i++) // compute output point { x->outlet[x->out[i].nbr_outlet] += x->out[i].mass1->posX * x->out[i].influence ; } // for (i=0; inb_outlet; i++) for (i=x->nb_outlet-1; i>=0; i--) // output everything on the corresponding outlet { outlet_float(x->taboutlet[i], x->outlet[i]); x->outlet[i] = 0; } } void pmpd_forceX(t_pmpd *x, t_float nbr_mass, t_float force) { // add a force to a specific mass nbr_mass = max(0, min( x->nb_mass, (int)nbr_mass)); x->mass[(int)nbr_mass].forceX += force; } void pmpd_posX(t_pmpd *x, t_float nbr_mass, t_float posX) { // displace a mass to a certain position nbr_mass = max(0, min( x->nb_mass, (int)nbr_mass)); x->mass[(int)nbr_mass].posX = posX; } void pmpd_mass(t_pmpd *x, t_float Id, t_float M, t_float posX) // add a mass // Id, invM speedX posX forceX { if (M==0) M=1; x->mass[x->nb_mass].Id = (int)Id; x->mass[x->nb_mass].invM = 1/M; x->mass[x->nb_mass].speedX = 0; x->mass[x->nb_mass].posX = posX; x->mass[x->nb_mass].forceX = 0; x->nb_mass++ ; x->nb_mass = min ( nb_max_mass -1, x->nb_mass ); } void pmpd_link(t_pmpd *x, t_float Id, t_float mass_1, t_float mass_2, t_float K1, t_float D1) // add a link // Id, *mass1, *mass2, Ke, K1, D1, K2, D2; { x->link[x->nb_link].Id = (int)Id; x->link[x->nb_link].mass1 = &x->mass[max(0, min ( x->nb_mass, (int)mass_1))]; x->link[x->nb_link].mass2 = &x->mass[max(0, min ( x->nb_mass, (int)mass_2))]; x->link[x->nb_link].K1 = K1; x->link[x->nb_link].D1 = D1; x->nb_link++ ; x->nb_link = min ( nb_max_link -1, x->nb_link ); } void pmpd_out(t_pmpd *x, t_float Id, t_float nb_outlet, t_float mass_1, t_float influence) // add an output point // Id, nbr_outlet, *mass1, influence; { x->out[x->nb_out].Id = (int)Id; x->out[x->nb_out].nbr_outlet = max(0, min( x->nb_outlet,(int)nb_outlet)); x->out[x->nb_out].mass1 = &x->mass[max(0, min ( x->nb_mass, (int)mass_1))]; x->out[x->nb_out].influence = influence; x->nb_out++ ; x->nb_out = min ( nb_max_out - 1, x->nb_out ); } void pmpd_in(t_pmpd *x, t_float Id, t_float nb_inlet, t_float mass_1, t_float influence) //add an input point // Id, nbr_inlet, *mass1, influence; { x->in[x->nb_in].Id = (int)Id; x->in[x->nb_in].nbr_inlet = max(0, min( x->nb_inlet,(int)nb_inlet)); x->in[x->nb_in].mass1 = &x->mass[max(0, min ( x->nb_mass, (int)mass_1))]; x->in[x->nb_in].influence = influence; x->nb_in++; x->nb_in = min ( nb_max_in - 1, x->nb_in ); } void pmpd_forceX_1(t_pmpd *x, t_float force) { x->inlet[0] += force; } void pmpd_forceX_2(t_pmpd *x, t_float force) { x->inlet[1] += force; } void pmpd_forceX_3(t_pmpd *x, t_float force) { x->inlet[2] += force; } void pmpd_forceX_4(t_pmpd *x, t_float force) { x->inlet[3] += force; } void pmpd_forceX_5(t_pmpd *x, t_float force) { x->inlet[4] += force; } void pmpd_forceX_6(t_pmpd *x, t_float force) { x->inlet[5] += force; } void pmpd_forceX_7(t_pmpd *x, t_float force) { x->inlet[6] += force; } void pmpd_forceX_8(t_pmpd *x, t_float force) { x->inlet[7] += force; } void pmpd_forceX_9(t_pmpd *x, t_float force) { x->inlet[8] += force; } void pmpd_forceX_10(t_pmpd *x, t_float force) { x->inlet[9] += force; } void pmpd_forceX_11(t_pmpd *x, t_float force) { x->inlet[10]+= force; } void pmpd_forceX_12(t_pmpd *x, t_float force) { x->inlet[11]+= force; } void pmpd_forceX_13(t_pmpd *x, t_float force) { x->inlet[12]+= force; } void pmpd_forceX_14(t_pmpd *x, t_float force) { x->inlet[13]+= force; } void pmpd_forceX_15(t_pmpd *x, t_float force) { x->inlet[14]+= force; } void pmpd_forceX_16(t_pmpd *x, t_float force) { x->inlet[15]+= force; } void pmpd_forceX_17(t_pmpd *x, t_float force) { x->inlet[16]+= force; } void pmpd_forceX_18(t_pmpd *x, t_float force) { x->inlet[17]+= force; } void pmpd_forceX_19(t_pmpd *x, t_float force) { x->inlet[18]+= force; } void pmpd_forceX_20(t_pmpd *x, t_float force) { x->inlet[19]+= force; } void pmpd_reset(t_pmpd *x) { x->nb_link = 0; x->nb_mass = 1; x->nb_out= 0; x->nb_in= 0; } void *pmpd_new(t_symbol *s, int argc, t_atom *argv) { int i; char buffer[10]; t_pmpd *x = (t_pmpd *)pd_new(pmpd_class); pmpd_reset(x); x->nb_outlet= (int)atom_getfloatarg(1, argc, argv); x->nb_outlet= max(0, min(nb_max_outlet, x->nb_outlet) ); for(i=0; inb_outlet; i++) x->taboutlet[i]=outlet_new(&x->x_obj, 0); x->nb_inlet = (int)atom_getfloatarg(0, argc, argv); x->nb_inlet= max(0, min(nb_max_inlet, x->nb_inlet) ); for(i=0; inb_inlet; i++) { sprintf (buffer, "forceX_%i", i+1); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("forceX"), gensym(buffer)); } return (void *)x; } void pmpd_setup(void) { pmpd_class = class_new(gensym("pmpd"), (t_newmethod)pmpd_new, 0, sizeof(t_pmpd),CLASS_DEFAULT, A_GIMME, 0); class_addbang(pmpd_class, pmpd_bang); class_addmethod(pmpd_class, (t_method)pmpd_mass, gensym("mass"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_link, gensym("link"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_out, gensym("out"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_in, gensym("in"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_posX, gensym("posX"), A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX, gensym("forceX"), A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_1, gensym("forceX_1"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_2, gensym("forceX_2"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_3, gensym("forceX_3"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_4, gensym("forceX_4"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_5, gensym("forceX_5"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_6, gensym("forceX_6"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_7, gensym("forceX_7"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_8, gensym("forceX_8"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_9, gensym("forceX_9"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_10, gensym("forceX_10"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_11, gensym("forceX_11"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_12, gensym("forceX_12"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_13, gensym("forceX_13"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_14, gensym("forceX_14"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_15, gensym("forceX_15"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_16, gensym("forceX_16"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_17, gensym("forceX_17"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_18, gensym("forceX_18"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_19, gensym("forceX_19"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_forceX_20, gensym("forceX_20"), A_DEFFLOAT, 0); class_addmethod(pmpd_class, (t_method)pmpd_reset, gensym("reset"), 0); /* post(""); post(" pmpd = Physical Modeling for Pure Data"); post(" version "VERSION); post(" compiled "__DATE__); post(" Contact : cyrille.henry@la-kitchen.fr"); post(""); masse_setup() ; lia_setup() ; masse2D_setup() ; lia2D_setup() ; masse3D_setup() ; lia3D_setup() ; iAmbient2D_setup(); iLine2D_setup(); iSeg2D_setup(); iCircle2D_setup(); tSquare2D_setup(); tCircle2D_setup(); tLine2D_setup(); tSeg2D_setup(); tLia2D_setup(); iAmbient3D_setup(); iSphere3D_setup(); iPlane3D_setup(); iCircle3D_setup(); iCylinder3D_setup(); tLia3D_setup(); tCube3D_setup(); tPlane3D_setup(); tSphere3D_setup(); tCylinder3D_setup(); tCircle3D_setup(); pmpd_tilde_setup(); */ }