diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2005-05-02 15:39:24 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2005-05-02 15:39:24 +0000 |
commit | bf1bd0b97f46224b8a639303919f191698771684 (patch) | |
tree | ff045d30cf8cf40f4bb523dee80c4ff44ab5e9aa | |
parent | 08139b3d3bf914933c2e040e559d4a62ded735ea (diff) |
generalized 1,2,3 dimensions into templates
log(O(n)) search for symbols and indices
many optimizations
fixed memory leaks
better error reporting
dependent on flext 0.5.0
svn path=/trunk/externals/nusmuk/; revision=2882
-rw-r--r-- | msd.h | 987 | ||||
-rwxr-xr-x | msd/main.cpp | 924 | ||||
-rw-r--r-- | msd/package.txt | 6 | ||||
-rwxr-xr-x | msd2D/main.cpp | 1066 | ||||
-rw-r--r-- | msd2D/package.txt | 6 | ||||
-rwxr-xr-x | msd3D/main.cpp | 1127 | ||||
-rw-r--r-- | msd3D/package.txt | 6 |
7 files changed, 1005 insertions, 3117 deletions
@@ -0,0 +1,987 @@ + + +/* + msd - mass spring damper model for Pure Data or Max/MSP + + Copyright (C) 2005 Nicolas Montgermont + Written by Nicolas Montgermont for a Master's train in Acoustic, + Signal processing and Computing Applied to Music (ATIAM, Paris 6) + at La Kitchen supervised by Cyrille Henry. + + Based on Pure Data by Miller Puckette and others + Use FLEXT C++ Layer by Thomas Grill (xovo@gmx.net) + Based on pmpd by Cyrille Henry + + + Contact : Nicolas Montgermont, montgermont@la-kitchen.fr + Cyrille Henry, Cyrille.Henry@la-kitchen.fr + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Version 0.05 -- 28.04.2005 +*/ + +// include flext header +#include <flext.h> +#include <flmap.h> +#include <math.h> +#include <string.h> +#include <vector> +#include <map> + +// define constants +#define MSD_VERSION 0.05 + + +// check for appropriate flext version +#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) +#error You need at least flext version 0.5.0 +#endif + +#ifdef _MSC_VER +#define NEWARR(type,var,size) type *var = new type[size] +#define DELARR(var) delete[] var +#else +#define NEWARR(type,var,size) type var[size] +#define DELARR(var) ((void)0) +#endif + + +inline t_float sqr(t_float x) { return x*x; } + + +template<int N> class Link; + +template<int N> +class LinkList + : public std::vector<Link<N> *> +{ +public: + void insert(Link<N> *l) + { + for(typename LinkList::iterator it = begin(); it != end(); ++it) + if(*it == l) return; + // not found -> add + push_back(l); + } + + void erase(Link<N> *l) + { + for(typename LinkList::iterator it = begin(); it != end(); ++it) + if(*it == l) { + // found + std::vector<Link<N> *>::erase(it); + return; + } + } +}; + +template<int N> +class Mass { +public: + t_int nbr; + const t_symbol *Id; + bool mobile; + t_float invM; + t_float speed[N]; + t_float pos[N]; + t_float pos2[N]; + t_float force[N]; + t_float out_force[N]; + LinkList<N> links; + + Mass(t_int n,const t_symbol *id,bool mob,t_float m,t_float p[N]) + : nbr(n),Id(id) + , mobile(mob) + , invM(m?1.f/m:1) + { + for(int i = 0; i < N; ++i) { + pos[i] = pos2[i] = p[i]; + force[i] = speed[i] = 0; + } + } + + inline void setForce(int n,t_float f) { force[n] = f; } + + inline void setForce(t_float f[N]) + { + for(int i = 0; i < N; ++i) setForce(i,f[i]); + } + + inline void setPos(int n,t_float p) { pos[n] = pos2[n] = p; } + + inline void setPos(t_float p[N]) + { + for(int i = 0; i < N; ++i) setPos(i,p[i]); + } + + inline void compute(t_float limit[N][2]) + { + // compute new masses position only if mobile = 1 + if(mobile) { + for(int i = 0; i < N; ++i) { + t_float pold = pos[i]; + t_float pnew = force[i] * invM + 2*pold - pos2[i]; // x[n] =Fx[n]/M+2x[n]-x[n-1] + if(pnew < limit[i][0]) pnew = limit[i][0]; else if(pnew > limit[i][1]) pnew = limit[i][1]; + speed[i] = (pos[i] = pnew) - (pos2[i] = pold); // x[n-2] = x[n-1], x[n-1] = x[n],vx[n] = x[n] - x[n-1] + } + } + // clear forces + for(int i = 0; i < N; ++i) { + out_force[i] = force[i]; + force[i] = 0; // Fx[n] = 0 + } + } +}; + +template<int N> +class Link { +public: + t_int nbr; + const t_symbol *Id; + Mass<N> *mass1,*mass2; + t_float K1, D1, D2; + t_float longueur, long_min, long_max; + t_float distance_old; + + inline t_float compdist() const + { + const Mass<N> *m1 = mass1,*m2 = mass2; // cache locally + t_float distance; + if(N == 1) + distance = fabs(m1->pos[0]-m2->pos[0]); // L[n] = |x1 - x2| + else { + distance = 0; + for(int i = 0; i < N; ++i) distance += sqr(m1->pos[i]-m2->pos[i]); + distance = sqrt(distance); + } + return distance; + } + + Link(t_int n,const t_symbol *id,Mass<N> *m1,Mass<N> *m2,t_float k1,t_float d1,t_float d2,t_float lmin,t_float lmax) + : nbr(n),Id(id) + , mass1(m1),mass2(m2) + , K1(k1),D1(d1),D2(d2) + , long_min(lmin),long_max(lmax) + { + distance_old = longueur = compdist(); // L[n-1] + + mass1->links.insert(this); + mass2->links.insert(this); + } + + ~Link() + { + mass1->links.erase(this); + mass2->links.erase(this); + } + + // compute link forces + inline void compute() + { + Mass<N> *m1 = mass1,*m2 = mass2; // cache locally + t_float distance = compdist(); + + if (distance < long_min || distance > long_max || distance == 0) { + for(int i = 0; i < N; ++i) { + m1->force[i] -= D2 * m1->speed[i]; // Fx1[n] = -Fx, Fx1[n] = Fx1[n] - D2 * vx1[n-1] + m2->force[i] += D2 * m2->speed[i]; // Fx2[n] = Fx, Fx2[n] = Fx2[n] - D2 * vx2[n-1] + } + } + else { // Lmin < L < Lmax + const t_float F = (K1 * (distance - longueur) + D1 * (distance - distance_old))/distance ; // F[n] = k1 (L[n] - L[0])/L[n] + D1 (L[n] - L[n-1])/L[n] + for(int i = 0; i < N; ++i) { + const t_float Fn = F * (m1->pos[i] - m2->pos[i]); // Fx = F * Lx[n]/L[n] + m1->force[i] -= Fn + D2 * m1->speed[i]; // Fx1[n] = -Fx, Fx1[n] = Fx1[n] - D2 * vx1[n-1] + m2->force[i] += Fn - D2 * m2->speed[i]; // Fx2[n] = Fx, Fx2[n] = Fx2[n] - D2 * vx2[n-1] + } + } + + distance_old = distance; // L[n-1] = L[n] + } +}; + + +template <typename T> +class IndexMap + : public TablePtrMap<int,T,16> +{ +public: + typedef TablePtrMap<int,T,16> Parent; + + virtual ~IndexMap() { reset(); } + + void reset() + { + // delete all associated items + for(typename Parent::iterator it(*this); it; ++it) delete it.data(); + Parent::clear(); + } + +}; + +template <typename T> +class IDMap + : std::map<const t_symbol *,TablePtrMap<T,T,4> *> +{ +public: + // that's the container holding the data items (masses, links) of one ID + typedef TablePtrMap<T,T,4> Container; + // that's the map for the key ID (symbol,int) relating to the data items + typedef std::map<const t_symbol *,Container *> Parent; + + typedef typename Container::iterator iterator; + + IDMap() {} + + virtual ~IDMap() { reset(); } + + void reset() + { + typename Parent::iterator it; + for(it = Parent::begin(); it != Parent::end(); ++it) + delete it->second; + Parent::clear(); + } + + void insert(T item) + { + typename Parent::iterator it = Parent::find(item->Id); + Container *c; + if(it == Parent::end()) + Parent::operator[](item->Id) = c = new Container; + else + c = it->second; + c->insert(item,item); + } + + iterator find(const t_symbol *key) + { + typename Parent::iterator it = Parent::find(key); + if(it == Parent::end()) + return iterator(); + else { + Container *c = it->second; + return iterator(*c); + } + } + + void erase(T item) + { + typename Parent::iterator it = Parent::find(item->Id); + if(it != Parent::end()) it->second->remove(item); + } +}; + + +template<int N> +class msdN: + public flext_base +{ + FLEXT_HEADER_S(msdN,flext_base,setup) //class with setup + +public: + // constructor with no arguments + msdN(int argc,t_atom *argv) + : id_mass(0),id_link(0) + { + for(int i = 0; i < N; ++i) limit[i][0] = -1.e10,limit[i][1] = 1.e10; + + // --- define inlets and outlets --- + AddInAnything("bang, reset, etc."); // default inlet + AddOutAnything("infos on masses"); // outlet for integer count + AddOutAnything("control"); // outlet for bang + } + + virtual ~msdN() { clear(); } + +protected: + +// -------------------------------------------------------------- PROTECTED VARIABLES +// ----------------------------------------------------------------------------------- + + typedef Mass<N> t_mass; + typedef Link<N> t_link; + + IndexMap<t_link *> link; // links + IDMap<t_link *> linkids; // links by name + IndexMap<t_mass *> mass; // masses + IDMap<t_mass *> massids; // masses by name + + t_float limit[N][2]; // Limit values + int id_mass, id_link; + +// --------------------------------------------------------------- RESET +// ---------------------------------------------------------------------- + void m_reset() + { + clear(); + ToOutAnything(1,S_Reset,0,NULL); + } + +// -------------------------------------------------------------- COMPUTE +// ----------------------------------------------------------------------- + + void m_bang() + { + // update all links + for (typename IndexMap<t_link *>::iterator lit(link); lit; ++lit) lit.data()->compute(); + + // update all masses + for (typename IndexMap<t_mass *>::iterator mit(mass); mit; ++mit) mit.data()->compute(limit); + } + +// -------------------------------------------------------------- MASSES +// ---------------------------------------------------------------------- + + // add a mass + // Id, nbr, mobile, invM, speedX, posX, forceX + void m_mass(int argc,t_atom *argv) + { + if(argc != 3+N) { + error("mass : Id mobile mass X"); + return; + } + + t_float pos[N]; + for(int i = 0; i < N; ++i) pos[i] = GetAFloat(argv[3+i]); + + t_mass *m = new t_mass( + id_mass, // index + GetSymbol(argv[0]), // ID + GetABool(argv[1]), // mobile + GetAFloat(argv[2]), // mass + pos // pos + ); + + outmass(S_Mass,m); + + massids.insert(m); + mass.insert(id_mass++,m); + } + + // add a force to mass(es) named Id or No + void m_force(int argc,t_atom *argv,int n) + { + if(argc != 2) { + error("%s - %s Syntax : Id/Nomass value",thisName(),GetString(thisTag())); + return; + } + + const t_float f = GetAFloat(argv[1]); + + if(IsSymbol(argv[0])) { + typename IDMap<t_mass *>::iterator it; + for(it = massids.find(GetSymbol(argv[0])); it; ++it) { + t_mass *m = it.data(); + m->setForce(n,f); + } + } + else { + t_mass *m = mass.find(GetAInt(argv[0])); + if(m) + m->setForce(n,f); + else + error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + } + + inline void m_forceX(int argc,t_atom *argv) { m_force(argc,argv,0); } + inline void m_forceY(int argc,t_atom *argv) { m_force(argc,argv,1); } + inline void m_forceZ(int argc,t_atom *argv) { m_force(argc,argv,2); } + + // displace mass(es) named Id or No to a certain position + void m_pos(int argc,t_atom *argv,int n) + { + if(argc != 2) { + error("%s - %s Syntax : Id/Nomass value",thisName(),GetString(thisTag())); + return; + } + + const t_float p = GetAFloat(argv[1]); + if(p > limit[n][1] || p < limit[n][0]) return; + + if(IsSymbol(argv[0])) { + typename IDMap<t_mass *>::iterator it; + for(it = massids.find(GetSymbol(argv[0])); it; ++it) + it.data()->setPos(n,p); + } + else { + t_mass *m = mass.find(GetAInt(argv[0])); + if(m) + m->setPos(n,p); + else + error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + } + + inline void m_posX(int argc,t_atom *argv) { m_pos(argc,argv,0); } + inline void m_posY(int argc,t_atom *argv) { m_pos(argc,argv,1); } + inline void m_posZ(int argc,t_atom *argv) { m_pos(argc,argv,2); } + + // set mass No to mobile + void m_set_mobile(int argc,t_atom *argv,bool mob = true) + { + if (argc != 1) { + error("%s - %s Syntax : Idmass",thisName(),GetString(thisTag())); + return; + } + + t_mass *m = mass.find(GetAInt(argv[0])); + if(m) + m->mobile = mob; + else + error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + + // set mass No to fixed + inline void m_set_fixe(int argc,t_atom *argv) { m_set_mobile(argc,argv,false); } + + // Delete mass + void m_delete_mass(int argc,t_atom *argv) + { + if (argc != 1) { + error("%s - %s Syntax : Nomass",thisName(),GetString(thisTag())); + return; + } + + t_mass *m = mass.remove(GetAInt(argv[0])); + if(m) { + // Delete all associated links + for(typename std::vector<t_link *>::iterator it = m->links.begin(); it != m->links.end(); ++it) + deletelink(*it); + outmass(S_Mass_deleted,m); + massids.erase(m); + mass.remove(m->nbr); + delete m; + } + else + error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + + + // set X,Y,Z min/max + void m_limit(int argc,t_atom *argv,int n,int i) + { + if (argc != 1) + error("%s - %s Syntax : Value",thisName(),GetString(thisTag())); + else + limit[n][i] = GetAFloat(argv[0]); + } + + inline void m_Xmin(int argc,t_atom *argv) { m_limit(argc,argv,0,0); } + inline void m_Ymin(int argc,t_atom *argv) { m_limit(argc,argv,1,0); } + inline void m_Zmin(int argc,t_atom *argv) { m_limit(argc,argv,2,0); } + + inline void m_Xmax(int argc,t_atom *argv) { m_limit(argc,argv,0,1); } + inline void m_Ymax(int argc,t_atom *argv) { m_limit(argc,argv,1,1); } + inline void m_Zmax(int argc,t_atom *argv) { m_limit(argc,argv,2,1); } + +// -------------------------------------------------------------- LINKS +// --------------------------------------------------------------------- + + // add a link + // Id, *mass1, *mass2, K1, D1, D2, (Lmin,Lmax) + void m_link(int argc,t_atom *argv) + { + if (argc < 6 || argc > 8) { + error("%s - %s Syntax : Id Nomass1 Nomass2 K D1 D2 (Lmin Lmax)",thisName(),GetString(thisTag())); + return; + } + + t_mass *mass1 = mass.find(GetAInt(argv[1])); + t_mass *mass2 = mass.find(GetAInt(argv[2])); + + if(!mass1 || !mass2) { + error("%s - %s : Index not found",thisName(),GetString(thisTag())); + return; + } + + t_link *l = new t_link( + id_link, + GetSymbol(argv[0]), // ID + mass1,mass2, // pointer to mass1, mass2 + GetAFloat(argv[3]), // K1 + GetAFloat(argv[4]), // D1 + GetAFloat(argv[5]), // D2 + argc >= 7?GetFloat(argv[6]):0, + argc >= 8?GetFloat(argv[7]):32768 + ); + + linkids.insert(l); + link.insert(id_link++,l); + outlink(S_Link,l); + } + + // add interactor link + // Id, Id masses1, Id masses2, K1, D1, D2, (Lmin, Lmax) + void m_ilink(int argc,t_atom *argv) + { + if (argc < 6 || argc > 8) { + error("%s - %s Syntax : Id Idmass1 Idmass2 K D1 D2 (Lmin Lmax)",thisName(),GetString(thisTag())); + return; + } + + typename IDMap<t_mass *>::iterator it1,it2,it; + it1 = massids.find(GetSymbol(argv[1])); + it2 = massids.find(GetSymbol(argv[2])); + + for(; it1; ++it1) { + for(it = it2; it; ++it) { + t_link *l = new t_link( + id_link, + GetSymbol(argv[0]), // ID + it1.data(),it.data(), // pointer to mass1, mass2 + GetAFloat(argv[3]), // K1 + GetAFloat(argv[4]), // D1 + GetAFloat(argv[5]), // D2 + argc >= 7?GetFloat(argv[6]):0, + argc >= 8?GetFloat(argv[7]):32768 + ); + + linkids.insert(l); + link.insert(id_link++,l); + outlink(S_Link,l); + } + } + } + + // set rigidity of link(s) named Id + void m_setK(int argc,t_atom *argv) + { + if (argc != 2) { + error("%s - %s Syntax : IdLink Value",thisName(),GetString(thisTag())); + return; + } + + t_float k1 = GetAFloat(argv[1]); + typename IDMap<t_link *>::iterator it; + for(it = linkids.find(GetSymbol(argv[0])); it; ++it) + it.data()->K1 = k1; + } + + // set damping of link(s) named Id + void m_setD(int argc,t_atom *argv) + { + if (argc != 2) { + error("%s - %s Syntax : IdLink Value",thisName(),GetString(thisTag())); + return; + } + + t_float d1 = GetAFloat(argv[1]); + typename IDMap<t_link *>::iterator it; + for(it = linkids.find(GetSymbol(argv[0])); it; ++it) + it.data()->D1 = d1; + } + + // set damping of link(s) named Id + void m_setD2(int argc,t_atom *argv) + { + if (argc != 2) { + error("%s - %s Syntax : IdLink Value",thisName(),GetString(thisTag())); + return; + } + + t_float d2 = GetAFloat(argv[1]); + typename IDMap<t_link *>::iterator it; + for(it = linkids.find(GetSymbol(argv[0])); it; ++it) + it.data()->D2 = d2; + } + + // Delete link + void m_delete_link(int argc,t_atom *argv) + { + if (argc != 1) { + error("%s - %s Syntax : NoLink",thisName(),GetString(thisTag())); + return; + } + + t_link *l = link.find(GetAInt(argv[0])); + if(l) + deletelink(l); + else { + error("%s - %s : Index not found",thisName(),GetString(thisTag())); + return; + } + } + + +// -------------------------------------------------------------- GET +// ------------------------------------------------------------------- + + // get attributes + void m_get(int argc,t_atom *argv) + { + if(argc == 0) { + return; + } + + t_atom sortie[1+2*N]; + const t_symbol *auxtype = GetSymbol(argv[0]); + + if (argc == 1) { + if (auxtype == S_massesPos) { // get all masses positions + for(typename IndexMap<t_mass *>::iterator mit(mass); mit; ++mit) { + SetInt(sortie[0],mit.data()->nbr); + for(int i = 0; i < N; ++i) SetFloat(sortie[1+i],mit.data()->pos[i]); + ToOutAnything(0,S_massesPos,1+N,sortie); + } + } + else if (auxtype == S_massesForces) { // get all masses forces + for(typename IndexMap<t_mass *>::iterator mit(mass); mit; ++mit) { + SetInt(sortie[0],mit.data()->nbr); + for(int i = 0; i < N; ++i) SetFloat(sortie[1+i],mit.data()->out_force[i]); + ToOutAnything(0,S_massesForces,1+N,sortie); + } + } + else if (auxtype == S_linksPos) { // get all links positions + for(typename IndexMap<t_link *>::iterator lit(link); lit; ++lit) { + SetInt(sortie[0],lit.data()->nbr); + for(int i = 0; i < N; ++i) { + SetFloat(sortie[1+i],lit.data()->mass1->pos[i]); + SetFloat(sortie[1+N+i],lit.data()->mass2->pos[i]); + } + ToOutAnything(0,S_linksPos,1+2*N,sortie); + } + } + else { // get all masses speeds + for(typename IndexMap<t_mass *>::iterator mit(mass); mit; ++mit) { + SetInt(sortie[0],mit.data()->nbr); + for(int i = 0; i < N; ++i) SetFloat(sortie[1+i],mit.data()->speed[i]); + ToOutAnything(0,S_massesSpeeds,1+N,sortie); + } + } + return; + } + + // more than 1 args + if (auxtype == S_massesPos) // get mass positions + { + for(int j = 1; j<argc; j++) { + if(IsSymbol(argv[j])) { + typename IDMap<t_mass *>::iterator mit; + for(mit = massids.find(GetSymbol(argv[j])); mit; ++mit) { + SetSymbol(sortie[0],mit.data()->Id); + for(int i = 0; i < N; ++i) SetFloat(sortie[1],mit.data()->pos[i]); + ToOutAnything(0,S_massesPosId,1+N,sortie); + } + } + else { + t_mass *m = mass.find(GetAInt(argv[j])); + if(m) { + SetInt(sortie[0],m->nbr); + for(int i = 0; i < N; ++i) SetFloat(sortie[1],m->pos[i]); + ToOutAnything(0,S_massesPosNo,1+N,sortie); + } +// else +// error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + } + } + else if (auxtype == S_massesForces) // get mass forces + { + for(int j = 1; j<argc; j++) { + if(IsSymbol(argv[j])) { + typename IDMap<t_mass *>::iterator mit; + for(mit = massids.find(GetSymbol(argv[j])); mit; ++mit) { + SetSymbol(sortie[0],mit.data()->Id); + for(int i = 0; i < N; ++i) SetFloat(sortie[1+i],mit.data()->out_force[i]); + ToOutAnything(0,S_massesForcesId,1+N,sortie); + } + } + else { + t_mass *m = mass.find(GetAInt(argv[j])); + if(m) { + SetInt(sortie[0],m->nbr); + for(int i = 0; i < N; ++i) SetFloat(sortie[1+i],m->out_force[i]); + ToOutAnything(0,S_massesForcesNo,1+N,sortie); + } +// else +// error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + } + } + else if (auxtype == S_linksPos) // get links positions + { + for(int j = 1; j<argc; j++) { + if(IsSymbol(argv[j])) { + typename IDMap<t_link *>::iterator lit; + for(lit = linkids.find(GetSymbol(argv[j])); lit; ++lit) { + SetSymbol(sortie[0],lit.data()->Id); + for(int i = 0; i < N; ++i) { + SetFloat(sortie[1+i],lit.data()->mass1->pos[i]); + SetFloat(sortie[1+N+i],lit.data()->mass2->pos[i]); + } + ToOutAnything(0,S_linksPosId,1+2*N,sortie); + } + } + else { + t_link *l = link.find(GetAInt(argv[j])); + if(l) { + SetInt(sortie[0],l->nbr); + for(int i = 0; i < N; ++i) { + SetFloat(sortie[1+i],l->mass1->pos[i]); + SetFloat(sortie[1+N+i],l->mass2->pos[i]); + } + ToOutAnything(0,S_linksPosNo,1+2*N,sortie); + } +// else +// error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + } + } + else // get mass speeds + { + for(int j = 1; j<argc; j++) { + if(IsSymbol(argv[j])) { + typename IDMap<t_mass *>::iterator mit; + for(mit = massids.find(GetSymbol(argv[j])); mit; ++mit) { + SetSymbol(sortie[0],mit.data()->Id); + for(int i = 0; i < N; ++i) SetFloat(sortie[1+i],mit.data()->speed[i]); + ToOutAnything(0,S_massesSpeedsId,1+N,sortie); + } + } + else { + t_mass *m = mass.find(GetAInt(argv[j])); + if(m) { + SetInt(sortie[0],m->nbr); + for(int i = 0; i < N; ++i) SetFloat(sortie[1+i],m->speed[i]); + ToOutAnything(0,S_massesSpeedsNo,1+N,sortie); + } +// else +// error("%s - %s : Index not found",thisName(),GetString(thisTag())); + } + } + } + } + + // List of masses positions on first outlet + void m_mass_dumpl() + { + int sz = mass.size(); + NEWARR(t_atom,sortie,sz*N); + t_atom *s = sortie; + for(typename IndexMap<t_mass *>::iterator mit(mass); mit; ++mit) + for(int i = 0; i < N; ++i) SetFloat(*(s++),mit.data()->pos[i]); + ToOutAnything(0, S_massesPosL, sz*N, sortie); + DELARR(sortie); + } + + // List of masses forces on first outlet + void m_force_dumpl() + { + int sz = mass.size(); + NEWARR(t_atom,sortie,sz*N); + t_atom *s = sortie; + for(typename IndexMap<t_mass *>::iterator mit(mass); mit; ++mit) + for(int i = 0; i < N; ++i) SetFloat(*(s++),mit.data()->out_force[i]); + ToOutAnything(0, S_massesForcesL, sz*N, sortie); + DELARR(sortie); + } + + // List of masses and links infos on second outlet + void m_info_dumpl() + { + for(typename IndexMap<t_mass *>::iterator mit(mass); mit; ++mit) + outmass(S_Mass,mit.data()); + + for(typename IndexMap<t_link *>::iterator lit(link); lit; ++lit) + outlink(S_Link,lit.data()); + } + + +// -------------------------------------------------------------- SETUP +// --------------------------------------------------------------------- + +private: + + void clear() + { + linkids.reset(); + link.reset(); + + massids.reset(); + mass.reset(); + + id_mass = id_link = 0; + } + + void deletelink(t_link *l) + { + outlink(S_Link_deleted,l); + linkids.erase(l); + link.remove(l->nbr); + delete l; + } + + void outmass(const t_symbol *s,const t_mass *m) + { + t_atom sortie[4+N]; + SetInt((sortie[0]),m->nbr); + SetSymbol((sortie[1]),m->Id); + SetBool((sortie[2]),m->mobile); + SetFloat((sortie[3]),1.f/m->invM); + for(int i = 0; i < N; ++i) SetFloat((sortie[4+i]),m->pos[i]); + ToOutAnything(1,s,4+N,sortie); + } + + void outlink(const t_symbol *s,const t_link *l) + { + t_atom sortie[7]; + SetInt((sortie[0]),l->nbr); + SetSymbol((sortie[1]),l->Id); + SetInt((sortie[2]),l->mass1->nbr); + SetInt((sortie[3]),l->mass2->nbr); + SetFloat((sortie[4]),l->K1); + SetFloat((sortie[5]),l->D1); + SetFloat((sortie[6]),l->D2); + ToOutAnything(1,s,7,sortie); + } + + + // Static symbols + const static t_symbol *S_Reset; + const static t_symbol *S_Mass; + const static t_symbol *S_Link; + const static t_symbol *S_iLink; + const static t_symbol *S_Mass_deleted; + const static t_symbol *S_Link_deleted; + const static t_symbol *S_massesPos; + const static t_symbol *S_massesPosNo; + const static t_symbol *S_massesPosId; + const static t_symbol *S_linksPos; + const static t_symbol *S_linksPosNo; + const static t_symbol *S_linksPosId; + const static t_symbol *S_massesForces; + const static t_symbol *S_massesForcesNo; + const static t_symbol *S_massesForcesId; + const static t_symbol *S_massesSpeeds; + const static t_symbol *S_massesSpeedsNo; + const static t_symbol *S_massesSpeedsId; + const static t_symbol *S_massesPosL; + const static t_symbol *S_massesForcesL; + + static void setup(t_classid c) + { + S_Reset = MakeSymbol("Reset"); + S_Mass = MakeSymbol("Mass"); + S_Link = MakeSymbol("Link"); + S_iLink = MakeSymbol("iLink"); + S_Mass_deleted = MakeSymbol("Mass deleted"); + S_Link_deleted = MakeSymbol("Link deleted"); + S_massesPos = MakeSymbol("massesPos"); + S_massesPosNo = MakeSymbol("massesPosNo"); + S_massesPosId = MakeSymbol("massesPosId"); + S_linksPos = MakeSymbol("linksPos"); + S_linksPosNo = MakeSymbol("linksPosNo"); + S_linksPosId = MakeSymbol("linksPosId"); + S_massesForces = MakeSymbol("massesForces"); + S_massesForcesNo = MakeSymbol("massesForcesNo"); + S_massesForcesId = MakeSymbol("massesForcesId"); + S_massesSpeeds = MakeSymbol("massesSpeeds"); + S_massesSpeedsNo = MakeSymbol("massesSpeedsNo"); + S_massesSpeedsId = MakeSymbol("massesSpeedsId"); + S_massesPosL = MakeSymbol("massesPosL"); + S_massesForcesL = MakeSymbol("massesForcesL"); + + // --- set up methods (class scope) --- + + // register a bang method to the default inlet (0) + FLEXT_CADDBANG(c,0,m_bang); + + // set up tagged methods for the default inlet (0) + // the underscore _ after CADDMETHOD indicates that a message tag is used + // no, variable list or anything and all single arguments are recognized automatically, ... + FLEXT_CADDMETHOD_(c,0,"reset",m_reset); + + FLEXT_CADDMETHOD_(c,0,"forceX",m_forceX); + FLEXT_CADDMETHOD_(c,0,"posX",m_posX); + FLEXT_CADDMETHOD_(c,0,"Xmax",m_Xmax); + FLEXT_CADDMETHOD_(c,0,"Xmin",m_Xmin); + if(N >= 2) { + FLEXT_CADDMETHOD_(c,0,"forceY",m_forceY); + FLEXT_CADDMETHOD_(c,0,"posY",m_posY); + FLEXT_CADDMETHOD_(c,0,"Ymax",m_Ymax); + FLEXT_CADDMETHOD_(c,0,"Ymin",m_Ymin); + } + if(N >= 3) { + FLEXT_CADDMETHOD_(c,0,"forceZ",m_forceZ); + FLEXT_CADDMETHOD_(c,0,"posZ",m_posZ); + FLEXT_CADDMETHOD_(c,0,"Zmax",m_Zmax); + FLEXT_CADDMETHOD_(c,0,"Zmin",m_Zmin); + } + + FLEXT_CADDMETHOD_(c,0,"setMobile",m_set_mobile); + FLEXT_CADDMETHOD_(c,0,"setFixed",m_set_fixe); + FLEXT_CADDMETHOD_(c,0,"setK",m_setK); + FLEXT_CADDMETHOD_(c,0,"setD",m_setD); + FLEXT_CADDMETHOD_(c,0,"setD2",m_setD2); + FLEXT_CADDMETHOD_(c,0,"mass",m_mass); + FLEXT_CADDMETHOD_(c,0,"link",m_link); + FLEXT_CADDMETHOD_(c,0,"iLink",m_ilink); + FLEXT_CADDMETHOD_(c,0,"get",m_get); + FLEXT_CADDMETHOD_(c,0,"deleteLink",m_delete_link); + FLEXT_CADDMETHOD_(c,0,"deleteMass",m_delete_mass); + FLEXT_CADDMETHOD_(c,0,"massesPosL",m_mass_dumpl); + FLEXT_CADDMETHOD_(c,0,"infosL",m_info_dumpl); + FLEXT_CADDMETHOD_(c,0,"massesForcesL",m_force_dumpl); + } + + // for every registered method a callback has to be declared + FLEXT_CALLBACK(m_bang) + FLEXT_CALLBACK(m_mass_dumpl) + FLEXT_CALLBACK(m_info_dumpl) + FLEXT_CALLBACK(m_force_dumpl) + FLEXT_CALLBACK(m_reset) + FLEXT_CALLBACK_V(m_set_mobile) + FLEXT_CALLBACK_V(m_set_fixe) + FLEXT_CALLBACK_V(m_mass) + FLEXT_CALLBACK_V(m_link) + FLEXT_CALLBACK_V(m_ilink) + FLEXT_CALLBACK_V(m_Xmax) + FLEXT_CALLBACK_V(m_Xmin) + FLEXT_CALLBACK_V(m_forceX) + FLEXT_CALLBACK_V(m_posX) + FLEXT_CALLBACK_V(m_Ymax) + FLEXT_CALLBACK_V(m_Ymin) + FLEXT_CALLBACK_V(m_forceY) + FLEXT_CALLBACK_V(m_posY) + FLEXT_CALLBACK_V(m_Zmax) + FLEXT_CALLBACK_V(m_Zmin) + FLEXT_CALLBACK_V(m_forceZ) + FLEXT_CALLBACK_V(m_posZ) + FLEXT_CALLBACK_V(m_setK) + FLEXT_CALLBACK_V(m_setD) + FLEXT_CALLBACK_V(m_setD2) + FLEXT_CALLBACK_V(m_get) + FLEXT_CALLBACK_V(m_delete_link) + FLEXT_CALLBACK_V(m_delete_mass) +}; +// -------------------------------------------------------------- STATIC VARIABLES +// ------------------------------------------------------------------------------- + +#define MSD(NAME,CLASS,N) \ +const t_symbol \ + *msdN<N>::S_Reset,*msdN<N>::S_Mass, \ + *msdN<N>::S_Link,*msdN<N>::S_iLink, \ + *msdN<N>::S_Mass_deleted,*msdN<N>::S_Link_deleted, \ + *msdN<N>::S_massesPos,*msdN<N>::S_massesPosNo,*msdN<N>::S_massesPosId, \ + *msdN<N>::S_linksPos,*msdN<N>::S_linksPosNo,*msdN<N>::S_linksPosId, \ + *msdN<N>::S_massesForces,*msdN<N>::S_massesForcesNo,*msdN<N>::S_massesForcesId, \ + *msdN<N>::S_massesSpeeds,*msdN<N>::S_massesSpeedsNo,*msdN<N>::S_massesSpeedsId, \ + *msdN<N>::S_massesPosL,*msdN<N>::S_massesForcesL; \ +\ +typedef msdN<N> CLASS; \ +FLEXT_NEW_V(NAME,CLASS) diff --git a/msd/main.cpp b/msd/main.cpp index b87c26a..844b8f9 100755 --- a/msd/main.cpp +++ b/msd/main.cpp @@ -1,923 +1,3 @@ +#include "../msd.h" - -/* - msd - mass spring damper model for Pure Data or Max/MSP - - Copyright (C) 2005 Nicolas Montgermont - Written by Nicolas Montgermont for a Master's train in Acoustic, - Signal processing and Computing Applied to Music (ATIAM, Paris 6) - at La Kitchen supervised by Cyrille Henry. - - Based on Pure Data by Miller Puckette and others - Use FLEXT C++ Layer by Thomas Grill (xovo@gmx.net) - Based on pmpd by Cyrille Henry - - - Contact : Nicolas Montgermont, montgermont@la-kitchen.fr - Cyrille Henry, Cyrille.Henry@la-kitchen.fr - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Version 0.05 -- 28.04.2005 -*/ - -// include flext header -#include <flext.h> -#include <math.h> -#include <string.h> - -// define constants -#define MSD_VERSION 0.05 -#define nb_max_link 4000 -#define nb_max_mass 4000 -#define Id_length 20 - -// check for appropriate flext version -#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 401) -#error You need at least flext version 0.4.1 -#endif - -#define max(a,b) ( ((a) > (b)) ? (a) : (b) ) -#define min(a,b) ( ((a) < (b)) ? (a) : (b) ) - -#ifdef _MSC_VER -#define NEWARR(type,var,size) type *var = new type[size] -#define DELARR(var) delete[] var -#else -#define NEWARR(type,var,size) type var[size] -#define DELARR(var) ((void)0) -#endif - -typedef struct _mass { - t_symbol *Id; - t_int nbr; - t_int mobile; - t_float invM; - t_float speedX; - t_float posX; - t_float posX2; - t_float forceX; - t_float out_forceX; -} t_mass; - -typedef struct _link { - t_symbol *Id; - t_int nbr; - t_mass *mass1; - t_mass *mass2; - t_float K1, D1, D2; - t_float longx, longueur, long_min, long_max; - t_float distance_old; -} t_link; - - -class msd: - public flext_base -{ - FLEXT_HEADER_S(msd,flext_base,setup) //class with setup - -public: - // constructor with no arguments - msd(int argc,t_atom *argv) - { - - nb_link = 0; - nb_mass = 0; - id_mass = 0; - id_link = 0; - - // --- define inlets and outlets --- - AddInAnything("bang, reset, etc."); // default inlet - AddOutAnything("infos on masses"); // outlet for integer count - AddOutAnything("control"); // outlet for bang - } - - - -protected: - -// --------------------------------------------------------------- RESET -// ---------------------------------------------------------------------- - void m_reset() - { - t_int i; - t_mass **mi; - t_link **li; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - delete (*mi); - } - for (i=0, li=link; i<nb_link; li++,i++) { - delete (*li); - } - ToOutAnything(1,S_Reset,0,NULL); - nb_link = 0; - nb_mass = 0; - id_mass = 0; - id_link = 0; - } - -// -------------------------------------------------------------- COMPUTE -// ----------------------------------------------------------------------- - - void m_bang() - { - t_int i; - for (i=0; i<nb_link; i++) { - // compute link forces - t_link *li = link[i]; - t_mass *m1 = li->mass1,*m2 = li->mass2; - t_float distance = fabs(m1->posX-m2->posX); // L[n] = |x1 - x2| - - t_float Fx; - if (distance < li->long_min || distance > li->long_max || distance == 0) - Fx = 0; - else { // Lmin < L < Lmax - t_float F = (li->K1 * (distance - li->longueur) + li->D1 * (distance - li->distance_old))/distance ; // F[n] = k1 (L[n] - L[0])/L[n] + D1 (L[n] - L[n-1])/L[n] - Fx = F * (m1->posX - m2->posX); // Fx = F * Lx[n]/L[n] - } - - m1->forceX -= Fx + li->D2 * m1->speedX; // Fx1[n] = -Fx, Fx1[n] = Fx1[n] - D2 * vx1[n-1] - m2->forceX += Fx - li->D2 * m2->speedX; // Fx2[n] = Fx, Fx2[n] = Fx2[n] - D2 * vx2[n-1] - li->distance_old = distance; // L[n-1] = L[n] - } - - for (i=0; i<nb_mass; i++) { - t_mass *mi = mass[i]; - // compute new masses position only if mobile = 1 - if (mi->mobile == 1) { - t_float X_new = mi->forceX * mi->invM + 2*mi->posX - mi->posX2; // x[n] =Fx[n]/M+2x[n]-x[n-1] - mi->posX2 = mi->posX; // x[n-2] = x[n-1] - mi->posX = max(min(X_new,Xmax),Xmin); // x[n-1] = x[n] - mi->speedX = mi->posX - mi->posX2; // vx[n] = x[n] - x[n-1] - } - } - - for (i=0; i<nb_mass; i++) { - t_mass *mi = mass[i]; - // clear forces - mi->out_forceX = mi->forceX; - mi->forceX = 0; // Fx[n] = 0 - } - } - -// -------------------------------------------------------------- MASSES -// ---------------------------------------------------------------------- - void m_mass(int argc,t_atom *argv) - // add a mass - // Id, nbr, mobile, invM, speedX, posX, forceX - { - t_atom sortie[5], aux[2]; - t_float M; - - if (argc != 4) - error("mass : Id mobile mass X"); - - mass[nb_mass] = new t_mass; // new mass - mass[nb_mass]->Id = GetSymbol(argv[0]); // ID - mass[nb_mass]->mobile = GetInt(argv[1]); // mobile - if (GetFloat(argv[2])==0) - M=1; - else M = GetFloat(argv[2]); - mass[nb_mass]->invM = 1/(M); // 1/M - mass[nb_mass]->speedX = 0; // vx[n] - mass[nb_mass]->posX = GetFloat(argv[3]); // x[n] - mass[nb_mass]->posX2 = GetFloat(argv[3]); // x[n-1] - mass[nb_mass]->forceX = 0; // Fx[n] - mass[nb_mass]->nbr = id_mass; // id number - nb_mass++; - id_mass++; - nb_mass = min ( nb_max_mass -1, nb_mass ); - SetFloat((sortie[0]),id_mass-1); - SetSymbol((sortie[1]),GetSymbol(argv[0])); - SetFloat((sortie[2]),mass[nb_mass-1]->mobile); - SetFloat((sortie[3]),M); - SetFloat((sortie[4]),mass[nb_mass-1]->posX); - ToOutAnything(1,S_Mass,5,sortie); - } - - void m_forceX(int argc,t_atom *argv) - { - // add a force to mass(es) named Id or No - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("forceX : Idmass value"); - - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->forceX = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (sym == (*mi)->Id) - (*mi)->forceX = GetFloat(argv[1]); - } - } - - void m_posX(int argc,t_atom *argv) - { - // displace mass(es) named Id or No to a certain position - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("posX : Id/Nomass value"); - - if (GetFloat(argv[1]) < Xmax && GetFloat(argv[1]) > Xmin) - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->posX = GetFloat(argv[1]); - (*mi)->posX2 = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if (sym == (*mi)->Id) { - (*mi)->posX = GetFloat(argv[1]); - (*mi)->posX2 = GetFloat(argv[1]); - } - } - - void m_set_mobile(int argc,t_atom *argv) - { - // set mass No to mobile - t_int i,aux; - t_mass **mi; - - if (argc != 1) - error("setMobile : Idmass"); - - aux = GetInt(argv[0]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if ((*mi)->nbr == aux) - (*mi)->mobile = 1; - } - - } - - void m_set_fixe(int argc,t_atom *argv) - { - // set mass No to fixed - t_int i,aux; - t_mass **mi; - - if (argc != 1) - error("setFixed : Idmass"); - - aux = GetInt(argv[0]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if ((*mi)->nbr == aux) - (*mi)->mobile = 0; - } - - } - - void m_delete_mass(int argc,t_atom *argv) - { - // Delete mass - t_int i,nb_link_delete=0; - t_atom sortie[5]; - NEWARR(t_atom,aux,nb_link); - t_mass **mi; - t_link **li; - - if (argc != 1) - error("deleteMass : Nomass"); - - // Delete all associated links - for (i=0, li=link; i<nb_link; li++,i++) { - if ((*li)->mass1->nbr == GetAInt(argv[0]) || (*li)->mass2->nbr == GetAInt(argv[0])) { - SetFloat((aux[nb_link_delete]),(*li)->nbr); - nb_link_delete++; - } - } - - for (i=0; i<nb_link_delete;i++) - m_delete_link(1,&aux[i]); - - // Delete mass - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr == GetAInt(argv[0])) { - SetFloat((sortie[0]),(*mi)->nbr); - SetSymbol((sortie[1]),(*mi)->Id); - SetFloat((sortie[2]),(*mi)->mobile); - SetFloat((sortie[3]),1/(*mi)->invM); - SetFloat((sortie[4]),(*mi)->posX); - delete (*mi); - (*mi) = mass[nb_mass-1]; // copy last mass instead - nb_mass--; - ToOutAnything(1,S_Mass_deleted,5,sortie); - break; - } - - DELARR(aux); - } - - - void m_Xmax(int argc,t_atom *argv) - { - // set X max - if (argc != 1) - error("Xmax : Value"); - Xmax = GetFloat(argv[0]); - } - - void m_Xmin(int argc,t_atom *argv) - { - // set X min - if (argc != 1) - error("Xmin : Value"); - Xmin = GetFloat(argv[0]); - } - -// -------------------------------------------------------------- LINKS -// --------------------------------------------------------------------- - - void m_link(int argc,t_atom *argv) - // add a link - // Id, *mass1, *mass2, K1, D1, D2, (Lmin,Lmax) - { - t_atom sortie[7], aux[2]; - t_int i; - t_mass *mass1 = NULL; - t_mass *mass2 = NULL; - t_mass **mi; - - - if (argc < 6 || argc > 8) - error("link : Id Nomass1 Nomass2 K D1 D2 (Lmin Lmax)"); - - // check for existence of link masses: - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==GetInt(argv[1])) // pointer to mass1 - // we found mass1 - mass1 = (*mi); - else if ((*mi)->nbr==GetInt(argv[2])) // pointer to mass2 - // ... and mass2 - mass2 = (*mi); - - if (mass1 and mass2) - { - link[nb_link] = new t_link; // New pointer - link[nb_link]->Id = GetSymbol(argv[0]); // ID - link[nb_link]->mass1 = mass1; // pointer to mass1 - link[nb_link]->mass2 = mass2; // pointer to mass2 - link[nb_link]->K1 = GetFloat(argv[3]); // K1 - link[nb_link]->D1 = GetFloat(argv[4]); // D1 - link[nb_link]->D2 = GetFloat(argv[5]); // D2 - link[nb_link]->longx = link[nb_link]->mass1->posX - link[nb_link]->mass2->posX; // Lx[0] - if (link[nb_link]->longx < 0) - link[nb_link]->longueur = -link[nb_link]->longx; - else - link[nb_link]->longueur = link[nb_link]->longx ;// L[0] - link[nb_link]->nbr = id_link; // id number - link[nb_link]->distance_old = link[nb_link]->longueur; // L[n-1] - switch (argc) { - case 6 : - link[nb_link]->long_max = 32768; - link[nb_link]->long_min = 0; - break; - case 7 : - link[nb_link]->long_min = GetFloat(argv[6]); - link[nb_link]->long_max = 32768; - break; - case 8 : - link[nb_link]->long_min = GetFloat(argv[6]); - link[nb_link]->long_max = GetFloat(argv[7]); - break; - } - nb_link++; - id_link++; - nb_link = min ( nb_max_link -1, nb_link ); - SetFloat((sortie[0]),id_link-1); - SetSymbol((sortie[1]),link[nb_link-1]->Id); - SetFloat((sortie[2]),GetInt(argv[1])); - SetFloat((sortie[3]),GetInt(argv[2])); - SetFloat((sortie[4]),link[nb_link-1]->K1); - SetFloat((sortie[5]),link[nb_link-1]->D1); - SetFloat((sortie[6]),link[nb_link-1]->D2); - ToOutAnything(1,S_Link,7,sortie); - } - else - error("link : Cannot create link: Not all masses for this link have been created yet."); - } - - void m_ilink(int argc,t_atom *argv) - // add interactor link - // Id, Id masses1, Id masses2, K1, D1, D2, (Lmin, Lmax) - { - t_atom aux[2], arglist[8]; - t_int i,j,nbmass1=0,nbmass2=0; - NEWARR(t_int,imass1,nb_mass); - NEWARR(t_int,imass2,nb_mass); - t_symbol *Id1, *Id2; - t_mass **mi; - - if (argc < 6 || argc > 8) - error("ilink : Id Idmass1 Idmass2 K D1 D2 (Lmin Lmax)"); - - Id1 = GetSymbol(argv[1]); - Id2 = GetSymbol(argv[2]); - ToOutAnything(1,S_iLink,0,aux); - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - if (Id1 == (*mi)->Id) { - imass1[nbmass1]=i; - nbmass1++; - } - if (Id2 == (*mi)->Id) { - imass2[nbmass2]=i; - nbmass2++; - } - } - - for(i=0;i<nbmass1;i++) - for(j=0;j<nbmass2;j++) - if (imass1[i] != imass2[j]) { - SetSymbol((arglist[0]),GetSymbol(argv[0])); - SetFloat((arglist[1]),mass[imass1[i]]->nbr); - SetFloat((arglist[2]),mass[imass2[j]]->nbr); - SetFloat((arglist[3]),GetFloat(argv[3])); - SetFloat((arglist[4]),GetFloat(argv[4])); - SetFloat((arglist[5]),GetFloat(argv[5])); - switch (argc) { - case 7 : - SetFloat(arglist[6],GetFloat(argv[6])); - break; - case 8 : - SetFloat(arglist[6],GetFloat(argv[6])); - SetFloat(arglist[7],GetFloat(argv[7])); - break; - } - m_link(argc,arglist); - } - - DELARR(imass1); - DELARR(imass2); - } - - void m_setK(int argc,t_atom *argv) - { - // set rigidity of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setK : IdLink Value"); - - for (i=0, li=link; i<nb_link; li++,i++) - { - if (sym == (*li)->Id) - (*li)->K1 = GetFloat(argv[1]); - } - } - - void m_setD(int argc,t_atom *argv) - { - // set damping of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setD : IdLink Value"); - - for (i=0, li=link; i<nb_link; li++,i++) - { - if (sym == (*li)->Id) - (*li)->D1 = GetFloat(argv[1]); - } - } - - void m_setD2(int argc,t_atom *argv) - { - // set damping of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setD2 : IdLink Value"); - - for (i=0, li=link; i<nb_link; li++,i++) - { - if (sym == (*li)->Id) - (*li)->D2 = GetFloat(argv[1]); - } - } - - void m_delete_link(int argc,t_atom *argv) - { - // Delete link - t_int i; - t_atom sortie[7]; - t_link **li; - - if (argc != 1) - error("deleteLink : NoLink"); - - for (i=0, li=link; i<nb_link; li++,i++) - if ((*li)->nbr == GetInt(argv[0])) { - SetFloat((sortie[0]),(*li)->nbr); - SetSymbol((sortie[1]),(*li)->Id); - SetFloat((sortie[2]),(*li)->mass1->nbr); - SetFloat((sortie[3]),(*li)->mass2->nbr); - SetFloat((sortie[4]),(*li)->K1); - SetFloat((sortie[5]),(*li)->D1); - SetFloat((sortie[6]),(*li)->D2); - delete (*li); - (*li)=link[nb_link-1]; // copy last link instead - nb_link--; - ToOutAnything(1,S_Link_deleted,7,sortie); - break; - } - } - - -// -------------------------------------------------------------- GET -// ------------------------------------------------------------------- - - void m_get(int argc,t_atom *argv) - // get attributes - { - t_int i,j; - t_symbol *auxarg,*auxarg2, *auxtype; - t_atom sortie[3]; - t_mass **mi; - t_link **li; - - auxtype = GetSymbol(argv[0]); - auxarg = GetASymbol(argv[1]); //auxarg : & symbol, 0 else - if (argc == 1) - { - if (auxtype == S_massesPos) // get all masses positions - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->posX); - ToOutAnything(0,S_massesPos,2,sortie); - } - else if (auxtype == S_massesForces) // get all masses forces - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->out_forceX); - ToOutAnything(0,S_massesForces,2,sortie); - } - else if (auxtype == S_linksPos) // get all links positions - for (i=0, li=link; i<nb_link; li++,i++) - { - SetFloat(sortie[0],(*li)->nbr); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass2->posX); - ToOutAnything(0,S_linksPos,3,sortie); - } - else // get all masses speeds - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->speedX); - ToOutAnything(0,S_massesSpeeds,2,sortie); - } - } - else if (auxtype == S_massesPos) // get mass positions - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - { - int arg = GetInt(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==arg) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->posX); - ToOutAnything(0,S_massesPosNo,2,sortie); - } - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->posX); - ToOutAnything(0,S_massesPosId,2,sortie); - } - } - } - } - } - else if (auxtype == S_massesForces) // get mass forces - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - { - int arg = GetInt(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==arg) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->out_forceX); - ToOutAnything(0,S_massesForcesNo,2,sortie); - } - } - } - else //string - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->out_forceX); - ToOutAnything(0,S_massesForcesId,2,sortie); - } - } - } - } - } - else if (auxtype == S_linksPos) // get links positions - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - { - int arg = GetInt(argv[j]); - for (i=0, li=link; i<nb_link; li++,i++) - if ((*li)->nbr==arg) - { - SetFloat(sortie[0],(*li)->nbr); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass2->posX); - ToOutAnything(0,S_linksPosNo,3,sortie); - } - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, li=link; i<nb_link; li++,i++) - { - if (auxarg2==(*li)->Id) - { - SetSymbol(sortie[0],(*li)->Id); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass2->posX); - ToOutAnything(0,S_linksPosId,3,sortie); - } - } - } - } - } - else // get mass speeds - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - { - int arg = GetInt(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==arg) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->speedX); - ToOutAnything(0,S_massesSpeedsNo,2,sortie); - } - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->speedX); - ToOutAnything(0,S_massesSpeedsId,2,sortie); - } - } - } - } - } - - - } - - void m_mass_dumpl() - // List of masses positions on first outlet - { - NEWARR(t_atom,sortie,nb_mass); - t_int i; - t_mass **mi; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - SetFloat((sortie[i]),(*mi)->posX); - } - ToOutAnything(0, S_massesPosL, nb_mass, sortie); - DELARR(sortie); - } - - void m_force_dumpl() - // List of masses forces on first outlet - { - NEWARR(t_atom,sortie,nb_mass); - t_int i; - t_mass **mi; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - SetFloat((sortie[i]),(*mi)->out_forceX); - } - ToOutAnything(0, S_massesForcesL, nb_mass, sortie); - DELARR(sortie); - } - - void m_info_dumpl() - // List of masses and links infos on second outlet - { - t_atom sortie[7]; - t_int i; - t_mass **mi; - t_link **li; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - SetFloat((sortie[0]),(*mi)->nbr); - SetSymbol((sortie[1]),(*mi)->Id); - SetFloat((sortie[2]),(*mi)->mobile); - SetFloat((sortie[3]),1/(*mi)->invM); - SetFloat((sortie[4]),(*mi)->posX); - ToOutAnything(1, S_Mass, 5, sortie); - } - - for (i=0, li=link; i<nb_link; li++,i++) { - SetFloat((sortie[0]),(*li)->nbr); - SetSymbol((sortie[1]),(*li)->Id); - SetFloat((sortie[2]),(*li)->mass1->nbr); - SetFloat((sortie[3]),(*li)->mass2->nbr); - SetFloat((sortie[4]),(*li)->K1); - SetFloat((sortie[5]),(*li)->D1); - SetFloat((sortie[6]),(*li)->D2); - ToOutAnything(1, S_Link, 7, sortie); - } - - } - - -// -------------------------------------------------------------- PROTECTED VARIABLES -// ----------------------------------------------------------------------------------- - - t_link * link[nb_max_link]; // Pointer table on links - t_mass * mass[nb_max_mass]; // Pointer table on masses - t_float Xmin, Xmax; // Limit values - int nb_link, nb_mass, id_mass, id_link; - -// -------------------------------------------------------------- SETUP -// --------------------------------------------------------------------- - -private: - - // Static symbols - const static t_symbol *S_Reset; - const static t_symbol *S_Mass; - const static t_symbol *S_Link; - const static t_symbol *S_iLink; - const static t_symbol *S_Mass_deleted; - const static t_symbol *S_Link_deleted; - const static t_symbol *S_massesPos; - const static t_symbol *S_massesPosNo; - const static t_symbol *S_massesPosId; - const static t_symbol *S_linksPos; - const static t_symbol *S_linksPosNo; - const static t_symbol *S_linksPosId; - const static t_symbol *S_massesForces; - const static t_symbol *S_massesForcesNo; - const static t_symbol *S_massesForcesId; - const static t_symbol *S_massesSpeeds; - const static t_symbol *S_massesSpeedsNo; - const static t_symbol *S_massesSpeedsId; - const static t_symbol *S_massesPosL; - const static t_symbol *S_massesForcesL; - - void static setup(t_classid c) - { - - // --- set up methods (class scope) --- - - // register a bang method to the default inlet (0) - FLEXT_CADDBANG(c,0,m_bang); - - // set up tagged methods for the default inlet (0) - // the underscore _ after CADDMETHOD indicates that a message tag is used - // no, variable list or anything and all single arguments are recognized automatically, ... - FLEXT_CADDMETHOD_(c,0,"reset",m_reset); - FLEXT_CADDMETHOD_(c,0,"forceX",m_forceX); - FLEXT_CADDMETHOD_(c,0,"posX",m_posX); - FLEXT_CADDMETHOD_(c,0,"Xmax",m_Xmax); - FLEXT_CADDMETHOD_(c,0,"Xmin",m_Xmin); - FLEXT_CADDMETHOD_(c,0,"setMobile",m_set_mobile); - FLEXT_CADDMETHOD_(c,0,"setFixed",m_set_fixe); - FLEXT_CADDMETHOD_(c,0,"setK",m_setK); - FLEXT_CADDMETHOD_(c,0,"setD",m_setD); - FLEXT_CADDMETHOD_(c,0,"setD2",m_setD2); - FLEXT_CADDMETHOD_(c,0,"mass",m_mass); - FLEXT_CADDMETHOD_(c,0,"link",m_link); - FLEXT_CADDMETHOD_(c,0,"iLink",m_ilink); - FLEXT_CADDMETHOD_(c,0,"get",m_get); - FLEXT_CADDMETHOD_(c,0,"deleteLink",m_delete_link); - FLEXT_CADDMETHOD_(c,0,"deleteMass",m_delete_mass); - FLEXT_CADDMETHOD_(c,0,"massesPosL",m_mass_dumpl); - FLEXT_CADDMETHOD_(c,0,"infosL",m_info_dumpl); - FLEXT_CADDMETHOD_(c,0,"massesForcesL",m_force_dumpl); - } - - // for every registered method a callback has to be declared - FLEXT_CALLBACK(m_bang) - FLEXT_CALLBACK(m_mass_dumpl) - FLEXT_CALLBACK(m_info_dumpl) - FLEXT_CALLBACK(m_force_dumpl) - FLEXT_CALLBACK(m_reset) - FLEXT_CALLBACK_V(m_set_mobile) - FLEXT_CALLBACK_V(m_set_fixe) - FLEXT_CALLBACK_V(m_mass) - FLEXT_CALLBACK_V(m_link) - FLEXT_CALLBACK_V(m_ilink) - FLEXT_CALLBACK_V(m_Xmax) - FLEXT_CALLBACK_V(m_Xmin) - FLEXT_CALLBACK_V(m_setK) - FLEXT_CALLBACK_V(m_setD) - FLEXT_CALLBACK_V(m_setD2) - FLEXT_CALLBACK_V(m_forceX) - FLEXT_CALLBACK_V(m_posX) - FLEXT_CALLBACK_V(m_get) - FLEXT_CALLBACK_V(m_delete_link) - FLEXT_CALLBACK_V(m_delete_mass) -}; -// -------------------------------------------------------------- STATIC VARIABLES -// ------------------------------------------------------------------------------- - - const t_symbol *msd::S_Reset = MakeSymbol("Reset"); - const t_symbol *msd::S_Mass = MakeSymbol("Mass"); - const t_symbol *msd::S_Link = MakeSymbol("Link"); - const t_symbol *msd::S_iLink = MakeSymbol("iLink"); - const t_symbol *msd::S_Mass_deleted = MakeSymbol("Mass deleted"); - const t_symbol *msd::S_Link_deleted = MakeSymbol("Link deleted"); - const t_symbol *msd::S_massesPos = MakeSymbol("massesPos"); - const t_symbol *msd::S_massesPosNo = MakeSymbol("massesPosNo"); - const t_symbol *msd::S_massesPosId = MakeSymbol("massesPosId"); - const t_symbol *msd::S_linksPos = MakeSymbol("linksPos"); - const t_symbol *msd::S_linksPosNo = MakeSymbol("linksPosNo"); - const t_symbol *msd::S_linksPosId = MakeSymbol("linksPosId"); - const t_symbol *msd::S_massesForces = MakeSymbol("massesForces"); - const t_symbol *msd::S_massesForcesNo = MakeSymbol("massesForcesNo"); - const t_symbol *msd::S_massesForcesId = MakeSymbol("massesForcesId"); - const t_symbol *msd::S_massesSpeeds = MakeSymbol("massesSpeeds"); - const t_symbol *msd::S_massesSpeedsNo = MakeSymbol("massesSpeedsNo"); - const t_symbol *msd::S_massesSpeedsId = MakeSymbol("massesSpeedsId"); - const t_symbol *msd::S_massesPosL = MakeSymbol("massesPosL"); - const t_symbol *msd::S_massesForcesL = MakeSymbol("massesForcesL"); - -// instantiate the class (constructor has a variable argument list) -FLEXT_NEW_V("msd",msd) - - +MSD("msd",msd,1) diff --git a/msd/package.txt b/msd/package.txt index 39c00ee..c564a23 100644 --- a/msd/package.txt +++ b/msd/package.txt @@ -1,2 +1,4 @@ -NAME=msd
-SRCS=main.cpp
+NAME=msd +SRCS=main.cpp +HDRS=../msd.h + diff --git a/msd2D/main.cpp b/msd2D/main.cpp index 0c5f3fb..4539810 100755 --- a/msd2D/main.cpp +++ b/msd2D/main.cpp @@ -1,1065 +1,3 @@ +#include "../msd.h" - -/* - msd2D - mass spring damper model for Pure Data or Max/MSP - - Copyright (C) 2005 Nicolas Montgermont - Written by Nicolas Montgermont for a Master's train in Acoustic, - Signal processing and Computing Applied to Music (ATIAM, Paris 6) - at La Kitchen supervised by Cyrille Henry. - - Based on Pure Data by Miller Puckette and others - Use FLEXT C++ Layer by Thomas Grill (xovo@gmx.net) - Based on pmpd by Cyrille Henry - - - Contact : Nicolas Montgermont, montgermont@la-kitchen.fr - Cyrille Henry, Cyrille.Henry@la-kitchen.fr - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Version 0.05 -- 28.04.2005 -*/ - -// include flext header -#include <flext.h> -#include <math.h> - -// define constants -#define MSD2D_VERSION 0.05 -#define nb_max_link 4000 -#define nb_max_mass 4000 -#define Id_length 20 - -// check for appropriate flext version -#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 401) -#error You need at least flext version 0.4.1 -#endif - -#define max(a,b) ( ((a) > (b)) ? (a) : (b) ) -#define min(a,b) ( ((a) < (b)) ? (a) : (b) ) - -#ifdef _MSC_VER -#define NEWARR(type,var,size) type *var = new type[size] -#define DELARR(var) delete[] var -#else -#define NEWARR(type,var,size) type var[size] -#define DELARR(var) ((void)0) -#endif - - -typedef struct _mass { - t_symbol *Id; - t_int nbr; - t_int mobile; - t_float invM; - t_float speedX; - t_float posX; - t_float posX2; - t_float forceX; - t_float out_forceX; - t_float speedY; - t_float posY; - t_float posY2; - t_float forceY; - t_float out_forceY; -} t_mass; - -typedef struct _link { - t_symbol *Id; - t_int nbr; - t_mass *mass1; - t_mass *mass2; - t_float K1, D1, D2; - t_float longx, longy, longueur, long_min, long_max; - t_float distance_old; -} t_link; - - -inline t_float sqr(t_float x) { return x*x; } - -class msd2D: - public flext_base -{ - FLEXT_HEADER_S(msd2D,flext_base,setup) //class with setup - -public: - // constructor with no arguments - msd2D(int argc,t_atom *argv) - { - nb_link = 0; - nb_mass = 0; - id_mass = 0; - id_link = 0; - mouse_grab=0; - - // --- define inlets and outlets --- - AddInAnything("bang, reset, etc."); // default inlet - AddOutAnything("infos on masses"); // outlet for integer count - AddOutAnything("control"); // outlet for bang - } - -protected: - -// --------------------------------------------------------------- RESET -// ---------------------------------------------------------------------- - - void m_reset() - { - t_int i; - t_mass **mi; - t_link **li; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - delete (*mi); - } - for (i=0, li=link; i<nb_link; li++, i++) { - delete (*li); - } - ToOutAnything(1,S_Reset,0,NULL); - nb_link = 0; - nb_mass = 0; - id_mass = 0; - id_link = 0; - } - -// -------------------------------------------------------------- COMPUTE -// ----------------------------------------------------------------------- - - void m_bang() - { - t_int i; - for (i=0; i<nb_link; i++) { - t_link *li = link[i]; - t_mass *m1 = li->mass1,*m2 = li->mass2; - // compute link forces - t_float distance = sqrt(sqr(m1->posX-m2->posX) + sqr(m1->posY-m2->posY)); // L[n] = sqrt( (x1-x2)² +(y1-y2)²) - - t_float Fx,Fy; - if (distance < li->long_min || distance > li->long_max || distance == 0) - Fx = Fy = 0; - else { - t_float F = (li->K1 * (distance - li->longueur) + li->D1 * (distance - li->distance_old))/distance; // F[n] = k1 (L[n] - L[0])/L[n]+ D1 (L[n] - L[n-1])/L[n] - Fx = F * (m1->posX - m2->posX); // Fx = F * Lx[n]/L[n] - Fy = F * (m1->posY - m2->posY); // Fy = F * Ly[n]/L[n] - } - - m1->forceX -= Fx+li->D2*m1->speedX; // Fx1[n] = -Fx,Fx1[n] = Fx1[n] - D2 * vx1[n-1] - m1->forceY -= Fy+li->D2*m1->speedY; // Fy1[n] = -Fy,Fy1[n] = Fy1[n] - D2 * vy1[n-1] - m2->forceX += Fx-li->D2*m2->speedX; // Fx2[n] = Fx,Fx2[n] = Fx2[n] - D2 * vx2[n-1] - m2->forceY += Fy-li->D2*m2->speedY; // Fy2[n] = Fy,Fy1[n] = Fy1[n] - D2 * vy1[n-1] - li->distance_old = distance; // L[n-1] = L[n] - } - - for (i=0; i<nb_mass; i++) { - t_mass *mi = mass[i]; - // compute new masses position only if mobile = 1 - if (mi->mobile == 1) { - t_float X_new = mi->forceX * mi->invM + 2*mi->posX - mi->posX2; // x[n] =Fx[n]/M+2x[n]-x[n-1] - mi->posX2 = mi->posX; // x[n-2] = x[n-1] - mi->posX = max(min(X_new,Xmax),Xmin); // x[n-1] = x[n] - mi->speedX = mi->posX - mi->posX2; // vx[n] = x[n] - x[n-1] - t_float Y_new = mi->forceY * mi->invM + 2*mi->posY - mi->posY2; // x[n] =Fx[n]/M+2x[n]-x[n-1] - mi->posY2 = mi->posY; // x[n-2] = x[n-1] - mi->posY = max(min(Y_new,Ymax),Ymin); // x[n-1] = x[n] - mi->speedY = mi->posY - mi->posY2; // vx[n] = x[n] - x[n-1] - } - } - - for (i=0; i<nb_mass; i++) { - t_mass *mi = mass[i]; - // clear forces - mi->out_forceX = mi->forceX; - mi->out_forceY = mi->forceY; - mi->forceX = mi->forceY = 0; // Fx[n] = 0,Fy[n] = 0 - } - } - -// -------------------------------------------------------------- MASSES -// ---------------------------------------------------------------------- - - void m_mass(int argc,t_atom *argv) - // add a mass - // Id, nbr, mobile, invM, speedX Y, posX Y, forceX Y - { - t_atom sortie[6], aux[2]; - t_float M; - - if (argc != 5) - error("mass : Id mobile mass X Y"); - - mass[nb_mass] = new t_mass; // new mass - mass[nb_mass]->Id = GetSymbol(argv[0]); // ID - mass[nb_mass]->mobile = GetInt(argv[1]); // mobile - if (GetFloat(argv[2])==0) - M=1; - else M = GetFloat(argv[2]); - mass[nb_mass]->invM = 1/(M); // invM - mass[nb_mass]->speedX = 0; // vx[n] - mass[nb_mass]->posX = GetFloat(argv[3]); // x[n] - mass[nb_mass]->posX2 = GetFloat(argv[3]); // x[n-1] - mass[nb_mass]->forceX = 0; // Fx[n] - mass[nb_mass]->speedY = 0; // vy[n] - mass[nb_mass]->posY = GetFloat(argv[4]); // y[n] - mass[nb_mass]->posY2 = GetFloat(argv[4]); // y[n-1] - mass[nb_mass]->forceY = 0; // Fy[n] - mass[nb_mass]->nbr = id_mass; // id number - nb_mass++ ; - id_mass++; - nb_mass = min ( nb_max_mass -1, nb_mass ); - SetFloat((sortie[0]),id_mass-1); - SetSymbol((sortie[1]),GetSymbol(argv[0])); - SetFloat((sortie[2]),mass[nb_mass-1]->mobile); - SetFloat((sortie[3]),M); - SetFloat((sortie[4]),mass[nb_mass-1]->posX); - SetFloat((sortie[5]),mass[nb_mass-1]->posY); - ToOutAnything(1,S_Mass,6,sortie); - } - - void m_forceX(int argc,t_atom *argv) - { - // add a force to mass(es) named Id or No - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("forceX : Idmass value"); - - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->forceX = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (sym == (*mi)->Id) - (*mi)->forceX = GetFloat(argv[1]); - } - } - - void m_forceY(int argc,t_atom *argv) - { - // add a force to mass(es) named Id or No - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("forceX : Idmass value"); - - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->forceY = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (sym == (*mi)->Id) - (*mi)->forceY = GetFloat(argv[1]); - } - } - - void m_posX(int argc,t_atom *argv) - { - // displace mass(es) named Id to a certain position - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("posX : Id/Nomass value"); - - if (GetFloat(argv[1]) < Xmax && GetFloat(argv[1]) > Xmin) - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->posX = GetFloat(argv[1]); - (*mi)->posX2 = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if (sym == (*mi)->Id) { - (*mi)->posX = GetFloat(argv[1]); - (*mi)->posX2 = GetFloat(argv[1]); - } - } - - void m_posY(int argc,t_atom *argv) - { - // displace mass(es) named Id to a certain position - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("posY : Id/Nomass value"); - - if (GetFloat(argv[1]) < Ymax && GetFloat(argv[1]) > Ymin) - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->posY = GetFloat(argv[1]); - (*mi)->posY2 = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if (sym == (*mi)->Id) { - (*mi)->posY = GetFloat(argv[1]); - (*mi)->posY2 = GetFloat(argv[1]); - } - } - - void m_set_mobile(int argc,t_atom *argv) - { - // set mass No to mobile - t_int i,aux; - t_mass **mi; - - if (argc != 1) - error("setMobile : Idmass"); - - aux = GetInt(argv[0]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if ((*mi)->nbr == aux) - (*mi)->mobile = 1; - } - - } - - void m_set_fixe(int argc,t_atom *argv) - { - // set mass No to fixed - t_int i,aux; - t_mass **mi; - - if (argc != 1) - error("setFixed : Idmass"); - - aux = GetAInt(argv[0]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if ((*mi)->nbr == aux) - (*mi)->mobile = 0; - } - - } - - void m_delete_mass(int argc,t_atom *argv) - { - // Delete mass - t_int i,nb_link_delete=0; - t_atom sortie[6]; - NEWARR(t_atom,aux,nb_link); - t_mass **mi; - t_link **li; - - if (argc != 1) - error("deleteMass : Nomass"); - - // Delete associated links - for (i=0, li=link; i<nb_link; li++, i++) { - if ((*li)->mass1->nbr == GetInt(argv[0]) || (*li)->mass2->nbr == GetInt(argv[0])) { - SetFloat((aux[nb_link_delete]),(*li)->nbr); - nb_link_delete++; - } - } - - for (i=0; i<nb_link_delete;i++) - m_delete_link(1,&aux[i]); - - // delete mass - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr == GetAInt(argv[0])) { - SetFloat((sortie[0]),(*mi)->nbr); - SetSymbol((sortie[1]),(*mi)->Id); - SetFloat((sortie[2]),(*mi)->mobile); - SetFloat((sortie[3]),1/(*mi)->invM); - SetFloat((sortie[4]),(*mi)->posX); - SetFloat((sortie[5]),(*mi)->posY); - delete (*mi); - (*mi) = mass[nb_mass-1]; - nb_mass--; - ToOutAnything(1,S_Mass_deleted,6,sortie); - break; - } - DELARR(aux); - } - - - void m_Xmax(int argc,t_atom *argv) - { - // set X max - if (argc != 1) - error("Xmax : Value"); - Xmax = GetFloat(argv[0]); - } - - void m_Xmin(int argc,t_atom *argv) - { - // set X min - if (argc != 1) - error("Xmin : Value"); - Xmin = GetFloat(argv[0]); - } - void m_Ymax(int argc,t_atom *argv) - { - // set Y max - if (argc != 1) - error("Ymax : Value"); - Ymax = GetFloat(argv[0]); - } - - void m_Ymin(int argc,t_atom *argv) - { - // set Y min - if (argc != 1) - error("Ymin : Value"); - Ymin = GetFloat(argv[0]); - } - - void m_grab_mass(int argc,t_atom *argv) - { - // grab nearest mass X Y - t_mass **mi; - t_float aux, distance; - t_int i; - - // if click - if (GetInt(argv[2])==1 && nb_mass>0) { - - if (argc != 3) - error("grabMass : X Y click"); - // first time we grab this mass?Find nearest mass - if (mouse_grab == 0) { - aux = pow(mass[0]->posX-GetFloat(argv[0]),2) + pow(mass[0]->posY-GetFloat(argv[1]),2); - nearest_mass = 0; - for (i=1, mi=(mass+1); i<nb_mass; mi++, i++) { - distance = pow((*mi)->posX-GetFloat(argv[0]),2) + pow((*mi)->posY-GetFloat(argv[1]),2); - if (distance<aux) { - aux = distance; - nearest_mass = i; - } - } - } - - // Set fixed if mobile - i = mass[nearest_mass]->mobile; - mass[nearest_mass]->mobile = 0; - - // Set XY - mass[nearest_mass]->posX = GetFloat(argv[0]); - mass[nearest_mass]->posX2 = GetFloat(argv[0]); - mass[nearest_mass]->posY = GetFloat(argv[1]); - mass[nearest_mass]->posY2 = GetFloat(argv[1]); - - // Set mobile - mass[nearest_mass]->mobile = i; - - // Current grabbing on - mouse_grab = 1; - } - else - // Grabing off - mouse_grab =0; - } -// -------------------------------------------------------------- LINKS -// --------------------------------------------------------------------- - - void m_link(int argc,t_atom *argv) - // add a link - // Id, *mass1, *mass2, K1, D1, D2, (Lmin,Lmax) - { - t_atom sortie[7], aux[2]; - t_int i; - t_mass *mass1 = NULL; - t_mass *mass2 = NULL; - t_mass **mi; - - if (argc < 6 || argc > 8) - error("link : Id Nomass1 Nomass2 K D1 D2 (Lmin Lmax)"); - - // check for existence of link masses: - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==GetInt(argv[1])) // pointer to mass1 - // we found mass1 - mass1 = (*mi); - else if ((*mi)->nbr==GetInt(argv[2])) // pointer to mass2 - // ... and mass2 - mass2 = (*mi); - - if (mass1 and mass2) - { - link[nb_link] = new t_link; // New pointer - link[nb_link]->Id = GetSymbol(argv[0]); // ID - link[nb_link]->mass1 = mass1; // pointer to mass1 - link[nb_link]->mass2 = mass2; // pointer to mass2 - link[nb_link]->K1 = GetFloat(argv[3]); // K1 - link[nb_link]->D1 = GetFloat(argv[4]); // D1 - link[nb_link]->D2 = GetFloat(argv[5]); // D2 - link[nb_link]->longx = link[nb_link]->mass1->posX - link[nb_link]->mass2->posX; // Lx[0] - link[nb_link]->longy = link[nb_link]->mass1->posY - link[nb_link]->mass2->posY; // Ly[0] - link[nb_link]->longueur = sqrt(pow(link[nb_link]->longx,2)+pow(link[nb_link]->longy,2)); // L[0] - link[nb_link]->nbr = id_link; // id number - link[nb_link]->distance_old = link[nb_link]->longueur; // L[n-1] - switch (argc) { - case 6 : - link[nb_link]->long_max = 32768; - link[nb_link]->long_min = 0; - break; - case 7 : - link[nb_link]->long_min = GetFloat(argv[6]); - link[nb_link]->long_max = 32768; - break; - case 8 : - link[nb_link]->long_min = GetFloat(argv[6]); - link[nb_link]->long_max = GetFloat(argv[7]); - break; - } - nb_link++; - id_link++; - nb_link = min ( nb_max_link -1, nb_link ); - SetFloat((sortie[0]),id_link-1); - SetSymbol((sortie[1]),link[nb_link-1]->Id); - SetFloat((sortie[2]),GetInt(argv[1])); - SetFloat((sortie[3]),GetInt(argv[2])); - SetFloat((sortie[4]),link[nb_link-1]->K1); - SetFloat((sortie[5]),link[nb_link-1]->D1); - SetFloat((sortie[6]),link[nb_link-1]->D2); - ToOutAnything(1,S_Link,7,sortie); - } - else - error("link : Cannot create link: Not all masses for this link have been created yet."); - } - - void m_ilink(int argc,t_atom *argv) - // add interactor link - // Id, Id masses1, Id masses2, K1, D1, D2, (Lmin, Lmax) - { - t_atom aux[2], arglist[8]; - t_int i,j, nbmass1=0, nbmass2=0; - NEWARR(t_int,imass1,nb_mass); - NEWARR(t_int,imass2,nb_mass); - t_symbol *Id1, *Id2; - t_mass **mi; - - if (argc < 6 || argc > 8) - error("ilink : Id Idmass1 Idmass2 K D1 D2 (Lmin Lmax)"); - - Id1 = GetSymbol(argv[1]); - Id2 = GetSymbol(argv[2]); - ToOutAnything(1,S_iLink,0,aux); - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - if (Id1 == (*mi)->Id) { - imass1[nbmass1]=i; - nbmass1++; - } - if (Id2 == (*mi)->Id) { - imass2[nbmass2]=i; - nbmass2++; - } - } - - for(i=0;i<nbmass1;i++) - for(j=0;j<nbmass2;j++) - if (imass1[i] != imass2[j]) { - SetSymbol((arglist[0]),GetSymbol(argv[0])); - SetFloat((arglist[1]),mass[imass1[i]]->nbr); - SetFloat((arglist[2]),mass[imass2[j]]->nbr); - SetFloat((arglist[3]),GetFloat(argv[3])); - SetFloat((arglist[4]),GetFloat(argv[4])); - SetFloat((arglist[5]),GetFloat(argv[5])); - switch (argc) { - case 7 : - SetFloat(arglist[6],GetFloat(argv[6])); - break; - case 8 : - SetFloat(arglist[6],GetFloat(argv[6])); - SetFloat(arglist[7],GetFloat(argv[7])); - break; - } - m_link(argc,arglist); - } - DELARR(imass1); - DELARR(imass2); - } - - void m_setK(int argc,t_atom *argv) - { - // set rigidity of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setK : IdLink Value"); - - for (i=0, li=link; i<nb_link; li++, i++) - { - if (sym == (*li)->Id) - (*li)->K1 = GetFloat(argv[1]); - } - } - - void m_setD(int argc,t_atom *argv) - { - // set damping of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setD : IdLink Value"); - - for (i=0, li=link; i<nb_link; li++, i++) - { - if (sym == (*li)->Id) - (*li)->D1 = GetFloat(argv[1]); - } - } - - void m_setD2(int argc,t_atom *argv) - { - // set damping of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setD2 : IdLink Value"); - - for (i=0, li=link; i<nb_link; li++, i++) - { - if (sym == (*li)->Id) - (*li)->D2 = GetFloat(argv[1]); - } - } - - void m_delete_link(int argc,t_atom *argv) - { - // Delete link - t_int i; - t_atom sortie[7]; - t_link **li; - - if (argc != 1) - error("deleteLink : NoLink"); - - for (i=0, li=link; i<nb_link; li++, i++) - if ((*li)->nbr == GetInt(argv[0])) { - SetFloat((sortie[0]),(*li)->nbr); - SetSymbol((sortie[1]),(*li)->Id); - SetFloat((sortie[2]),(*li)->mass1->nbr); - SetFloat((sortie[3]),(*li)->mass2->nbr); - SetFloat((sortie[4]),(*li)->K1); - SetFloat((sortie[5]),(*li)->D1); - SetFloat((sortie[6]),(*li)->D2); - delete (*li); - (*li)=link[nb_link-1]; // copy last link instead - nb_link--; - ToOutAnything(1,S_Link_deleted,7,sortie); - break; - } - } - - -// -------------------------------------------------------------- GET -// ------------------------------------------------------------------- - void m_get(int argc,t_atom *argv) - // get attributes - { - t_int i,j; - t_symbol *auxarg,*auxarg2, *auxtype; - t_atom sortie[5]; - auxtype = GetSymbol(argv[0]); - auxarg = GetASymbol(argv[1]); //auxarg : & symbol, 0 else - t_mass **mi; - t_link **li; - - if (argc == 1) - { - if (auxtype == S_massesPos) // get all masses positions - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->posX); - SetFloat(sortie[2],(*mi)->posY); - ToOutAnything(0,S_massesPos,3,sortie); - } - else if (auxtype == S_massesForces) // get all masses forces - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->out_forceX); - SetFloat(sortie[2],(*mi)->out_forceY); - ToOutAnything(0,S_massesForces,3,sortie); - } - else if (auxtype == S_linksPos) // get all links positions - for (i=0, li=link; i<nb_link; li++, i++) - { - SetFloat(sortie[0],(*li)->nbr); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass1->posY); - SetFloat(sortie[3],(*li)->mass2->posX); - SetFloat(sortie[4],(*li)->mass2->posY); - ToOutAnything(0,S_linksPos,5,sortie); - } - else // get all masses speeds - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->speedX); - SetFloat(sortie[2],(*mi)->speedY); - ToOutAnything(0,S_massesSpeeds,3,sortie); - } - } - else if (auxtype == S_massesPos) // get mass positions - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->posX); - SetFloat(sortie[2],(*mi)->posY); - ToOutAnything(0,S_massesPosNo,3,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->posX); - SetFloat(sortie[2],(*mi)->posY); - ToOutAnything(0,S_massesPosId,3,sortie); - } - } - } - } - } - else if (auxtype == S_massesForces) // get mass forces - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->out_forceX); - SetFloat(sortie[2],(*mi)->out_forceY); - ToOutAnything(0,S_massesForcesNo,3,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->out_forceX); - SetFloat(sortie[2],(*mi)->out_forceY); - ToOutAnything(0,S_massesForcesId,3,sortie); - } - } - } - } - } - else if (auxtype == S_linksPos) // get links positions - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, li=link; i<nb_link; li++, i++) - if ((*li)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*li)->nbr); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass1->posY); - SetFloat(sortie[3],(*li)->mass2->posX); - SetFloat(sortie[4],(*li)->mass2->posY); - ToOutAnything(0,S_linksPosNo,5,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, li=link; i<nb_link; li++, i++) - { - if (auxarg2==(*li)->Id) - { - SetSymbol(sortie[0],(*li)->Id); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass1->posY); - SetFloat(sortie[3],(*li)->mass2->posX); - SetFloat(sortie[4],(*li)->mass2->posY); - ToOutAnything(0,S_linksPosId,5,sortie); - } - } - } - } - } - else // get mass speeds - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if ((*mi)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->speedX); - SetFloat(sortie[2],(*mi)->speedY); - ToOutAnything(0,S_massesSpeedsNo,3,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->speedX); - SetFloat(sortie[2],(*mi)->speedY); - ToOutAnything(0,S_massesSpeedsId,3,sortie); - } - } - } - } - } - - - } - - void m_mass_dumpl() - // List of masses positions on first outlet - { - NEWARR(t_atom,sortie,2*nb_mass); - t_int i; - t_mass **mi; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - SetFloat((sortie[2*i]),(*mi)->posX); - SetFloat((sortie[2*i+1]),(*mi)->posY); - } - ToOutAnything(0, S_massesPosL, 2*nb_mass, sortie); - DELARR(sortie); - } - - void m_force_dumpl() - // List of masses forces on first outlet - { - NEWARR(t_atom,sortie,2*nb_mass); - t_int i; - t_mass **mi; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - SetFloat((sortie[2*i]),(*mi)->out_forceX); - SetFloat((sortie[2*i+1]),(*mi)->out_forceY); - } - ToOutAnything(0, S_massesForcesL, 2*nb_mass, sortie); - DELARR(sortie); - } - - void m_info_dumpl() - // List of infos on masses and links on first outlet - { - t_atom sortie[7]; - t_int i; - t_mass **mi; - t_link **li; - - for (i=0, mi=mass; i<nb_mass; mi++, i++) { - SetFloat((sortie[0]),(*mi)->nbr); - SetSymbol((sortie[1]),(*mi)->Id); - SetFloat((sortie[2]),(*mi)->mobile); - SetFloat((sortie[3]),1/(*mi)->invM); - SetFloat((sortie[4]),(*mi)->posX); - SetFloat((sortie[5]),(*mi)->posY); - ToOutAnything(1, S_Mass, 6, sortie); - } - - for (i=0, li=link; i<nb_link; li++, i++) { - SetFloat((sortie[0]),(*li)->nbr); - SetSymbol((sortie[1]),(*li)->Id); - SetFloat((sortie[2]),(*li)->mass1->nbr); - SetFloat((sortie[3]),(*li)->mass2->nbr); - SetFloat((sortie[4]),(*li)->K1); - SetFloat((sortie[5]),(*li)->D1); - SetFloat((sortie[6]),(*li)->D2); - ToOutAnything(1, S_Link, 7, sortie); - } - - } - -// -------------------------------------------------------------- GLOBAL VARIABLES -// -------------------------------------------------------------------------------- - - t_link * link[nb_max_link]; - t_mass * mass[nb_max_mass]; - t_float Xmin, Xmax, Ymin, Ymax; - t_int nb_link, nb_mass, id_mass, id_link, mouse_grab, nearest_mass; - -// -------------------------------------------------------------- SETUP -// --------------------------------------------------------------------- - -private: - - // static symbols - const static t_symbol *S_Reset; - const static t_symbol *S_Mass; - const static t_symbol *S_Link; - const static t_symbol *S_iLink; - const static t_symbol *S_Mass_deleted; - const static t_symbol *S_Link_deleted; - const static t_symbol *S_massesPos; - const static t_symbol *S_massesPosNo; - const static t_symbol *S_massesPosId; - const static t_symbol *S_linksPos; - const static t_symbol *S_linksPosNo; - const static t_symbol *S_linksPosId; - const static t_symbol *S_massesForces; - const static t_symbol *S_massesForcesNo; - const static t_symbol *S_massesForcesId; - const static t_symbol *S_massesSpeeds; - const static t_symbol *S_massesSpeedsNo; - const static t_symbol *S_massesSpeedsId; - const static t_symbol *S_massesPosL; - const static t_symbol *S_massesForcesL; - - static void setup(t_classid c) - { - - // --- set up methods (class scope) --- - - // register a bang method to the default inlet (0) - FLEXT_CADDBANG(c,0,m_bang); - - // set up tagged methods for the default inlet (0) - // the underscore _ after CADDMETHOD indicates that a message tag is used - // no, variable list or anything and all single arguments are recognized automatically, ... - FLEXT_CADDMETHOD_(c,0,"reset",m_reset); - FLEXT_CADDMETHOD_(c,0,"forceX",m_forceX); - FLEXT_CADDMETHOD_(c,0,"forceY",m_forceY); - FLEXT_CADDMETHOD_(c,0,"posX",m_posX); - FLEXT_CADDMETHOD_(c,0,"Xmax",m_Xmax); - FLEXT_CADDMETHOD_(c,0,"Xmin",m_Xmin); - FLEXT_CADDMETHOD_(c,0,"Ymax",m_Ymax); - FLEXT_CADDMETHOD_(c,0,"Ymin",m_Ymin); - FLEXT_CADDMETHOD_(c,0,"posY",m_posY); - FLEXT_CADDMETHOD_(c,0,"setK",m_setK); - FLEXT_CADDMETHOD_(c,0,"setD",m_setD); - FLEXT_CADDMETHOD_(c,0,"setD2",m_setD2); - FLEXT_CADDMETHOD_(c,0,"mass",m_mass); - FLEXT_CADDMETHOD_(c,0,"link",m_link); - FLEXT_CADDMETHOD_(c,0,"iLink",m_ilink); - FLEXT_CADDMETHOD_(c,0,"get",m_get); - FLEXT_CADDMETHOD_(c,0,"deleteLink",m_delete_link); - FLEXT_CADDMETHOD_(c,0,"deleteMass",m_delete_mass); - FLEXT_CADDMETHOD_(c,0,"massesPosL",m_mass_dumpl); - FLEXT_CADDMETHOD_(c,0,"infosL",m_info_dumpl); - FLEXT_CADDMETHOD_(c,0,"massesForcesL",m_force_dumpl); - FLEXT_CADDMETHOD_(c,0,"setMobile",m_set_mobile); - FLEXT_CADDMETHOD_(c,0,"setFixed",m_set_fixe); - FLEXT_CADDMETHOD_(c,0,"grabMass",m_grab_mass); - } - - // for every registered method a callback has to be declared - FLEXT_CALLBACK(m_bang) - FLEXT_CALLBACK(m_mass_dumpl) - FLEXT_CALLBACK(m_force_dumpl) - FLEXT_CALLBACK(m_info_dumpl) - FLEXT_CALLBACK(m_reset) - FLEXT_CALLBACK_V(m_mass) - FLEXT_CALLBACK_V(m_link) - FLEXT_CALLBACK_V(m_ilink) - FLEXT_CALLBACK_V(m_set_mobile) - FLEXT_CALLBACK_V(m_set_fixe) - FLEXT_CALLBACK_V(m_Xmax) - FLEXT_CALLBACK_V(m_Xmin) - FLEXT_CALLBACK_V(m_Ymax) - FLEXT_CALLBACK_V(m_Ymin) - FLEXT_CALLBACK_V(m_setK) - FLEXT_CALLBACK_V(m_setD) - FLEXT_CALLBACK_V(m_setD2) - FLEXT_CALLBACK_V(m_forceX) - FLEXT_CALLBACK_V(m_forceY) - FLEXT_CALLBACK_V(m_posX) - FLEXT_CALLBACK_V(m_posY) - FLEXT_CALLBACK_V(m_get) - FLEXT_CALLBACK_V(m_delete_link) - FLEXT_CALLBACK_V(m_delete_mass) - FLEXT_CALLBACK_V(m_grab_mass) -}; - - const t_symbol *msd2D::S_Reset = MakeSymbol("Reset"); - const t_symbol *msd2D::S_Mass = MakeSymbol("Mass"); - const t_symbol *msd2D::S_Link = MakeSymbol("Link"); - const t_symbol *msd2D::S_iLink = MakeSymbol("iLink"); - const t_symbol *msd2D::S_Mass_deleted = MakeSymbol("Mass deleted"); - const t_symbol *msd2D::S_Link_deleted = MakeSymbol("Link deleted"); - const t_symbol *msd2D::S_massesPos = MakeSymbol("massesPos"); - const t_symbol *msd2D::S_massesPosNo = MakeSymbol("massesPosNo"); - const t_symbol *msd2D::S_massesPosId = MakeSymbol("massesPosId"); - const t_symbol *msd2D::S_linksPos = MakeSymbol("linksPos"); - const t_symbol *msd2D::S_linksPosNo = MakeSymbol("linksPosNo"); - const t_symbol *msd2D::S_linksPosId = MakeSymbol("linksPosId"); - const t_symbol *msd2D::S_massesForces = MakeSymbol("massesForces"); - const t_symbol *msd2D::S_massesForcesNo = MakeSymbol("massesForcesNo"); - const t_symbol *msd2D::S_massesForcesId = MakeSymbol("massesForcesId"); - const t_symbol *msd2D::S_massesSpeeds = MakeSymbol("massesSpeeds"); - const t_symbol *msd2D::S_massesSpeedsNo = MakeSymbol("massesSpeedsNo"); - const t_symbol *msd2D::S_massesSpeedsId = MakeSymbol("massesSpeedsId"); - const t_symbol *msd2D::S_massesPosL = MakeSymbol("massesPosL"); - const t_symbol *msd2D::S_massesForcesL = MakeSymbol("massesForcesL"); - -// instantiate the class (constructor has a variable argument list) -FLEXT_NEW_V("msd2D",msd2D) - - +MSD("msd2D",msd2D,2) diff --git a/msd2D/package.txt b/msd2D/package.txt index 2a14acc..fc47d72 100644 --- a/msd2D/package.txt +++ b/msd2D/package.txt @@ -1,2 +1,4 @@ -NAME=msd2D
-SRCS=main.cpp
+NAME=msd2D +SRCS=main.cpp +HDRS=../msd.h + diff --git a/msd3D/main.cpp b/msd3D/main.cpp index 3ca4597..79010f5 100755 --- a/msd3D/main.cpp +++ b/msd3D/main.cpp @@ -1,1126 +1,3 @@ +#include "../msd.h" - -/* - msd3D - mass spring damper model for Pure Data or Max/MSP - - Copyright (C) 2005 Nicolas Montgermont - Written by Nicolas Montgermont for a Master's train in Acoustic, - Signal processing and Computing Applied to Music (ATIAM, Paris 6) - at La Kitchen supervised by Cyrille Henry. - - Based on Pure Data by Miller Puckette and others - Use FLEXT C++ Layer by Thomas Grill (xovo@gmx.net) - Based on pmpd by Cyrille Henry - - - Contact : Nicolas Montgermont, montgermont@la-kitchen.fr - Cyrille Henry, Cyrille.Henry@la-kitchen.fr - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Version 0.05 -- 28.04.2005 -*/ - -// include flext header -#include <flext.h> -#include <math.h> - -// define constants -#define MSD3D_VERSION 0.05 -#define nb_max_link 4000 -#define nb_max_mass 4000 -#define Id_length 20 - -// check for appropriate flext version -#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 401) -#error You need at least flext version 0.4.1 -#endif - -#define max(a,b) ( ((a) > (b)) ? (a) : (b) ) -#define min(a,b) ( ((a) < (b)) ? (a) : (b) ) - -#ifdef _MSC_VER -#define NEWARR(type,var,size) type *var = new type[size] -#define DELARR(var) delete[] var -#else -#define NEWARR(type,var,size) type var[size] -#define DELARR(var) ((void)0) -#endif - - - -typedef struct _mass { - t_symbol *Id; - t_int nbr; - t_int mobile; - t_float invM; - t_float speedX; - t_float posX; - t_float posX2; - t_float forceX; - t_float out_forceX; - t_float speedY; - t_float posY; - t_float posY2; - t_float forceY; - t_float out_forceY; - t_float speedZ; - t_float posZ; - t_float posZ2; - t_float forceZ; - t_float out_forceZ; -} t_mass; - -typedef struct _link { - t_symbol *Id; - t_int nbr; - t_mass *mass1; - t_mass *mass2; - t_float K1, D1, D2; - t_float longx, longy, longz, longueur, long_min, long_max; - t_float distance_old; -} t_link; - -inline t_float sqr(t_float x) { return x*x; } - -class msd3D: - public flext_base -{ - FLEXT_HEADER_S(msd3D,flext_base,setup) //class with setup - -public: - // constructor with no arguments - msd3D(int argc,t_atom *argv) - { - nb_link = 0; - nb_mass = 0; - id_mass = 0; - id_link = 0; - - // --- define inlets and outlets --- - AddInAnything("bang, reset, etc."); // default inlet - AddOutAnything("infos on masses"); // outlet for integer count - AddOutAnything("control"); // outlet for bang - } - -protected: - -// --------------------------------------------------------------- RESET -// ---------------------------------------------------------------------- - void m_reset() - { - t_int i; - t_mass **mi; - t_link **li; - - for (i=0, mi=mass; i<nb_mass;mi++, i++) { - delete (*mi); - } - for (i=0, li=link; i<nb_link;li++, i++) { - delete (*li); - } - ToOutAnything(1,S_Reset,0,NULL); - nb_link = 0; - nb_mass = 0; - id_mass = 0; - id_link = 0; - } - -// -------------------------------------------------------------- COMPUTE -// ----------------------------------------------------------------------- - void m_bang() - { - t_int i; - for (i=0; i<nb_link; i++) { - t_link *li = link[i]; - t_mass *m1 = li->mass1,*m2 = li->mass2; - // compute link forces - t_float distance = sqrt(sqr(m1->posX-m2->posX) + sqr(m1->posY-m2->posY) + sqr(m1->posZ-m2->posZ)); // L[n] - t_float Fx,Fy,Fz; - if (distance < li->long_min || distance > li->long_max || distance == 0) - Fx = Fy = Fz = 0; - else { - t_float F = (li->K1 * (distance - li->longueur) + li->D1 * (distance - li->distance_old))/distance ; //F = K1(L[n] - L[0])/L[n] + D1(L[n] - L[n-1])/L[n] - Fx = F * (m1->posX - m2->posX); // Fx[n] = F * Lx[n] - Fy = F * (m1->posY - m2->posY); // Fy[n] = F * Ly[n] - Fz = F * (m1->posZ - m2->posZ); // Fy[n] = F * Lz[n] - } - m1->forceX -= Fx + li->D2*m1->speedX; // Fx1[n] = -Fx,Fx1[n] = Fx1[n] - D2 * vx1[n-1] - m2->forceX += Fx - li->D2*m2->speedX; //Fx2[n] = Fx, Fx2[n] = Fx2[n] - D2 * vx2[n-1] - m1->forceY -= Fy + li->D2*m1->speedY; // Fy1[n] = -Fy,Fy1[n] = Fy1[n] - D2 * vy1[n-1] - m2->forceY += Fy - li->D2*m2->speedY; // Fy2[n] = Fy,Fy2[n] = Fy2[n] - D2 * vy2[n-1] - m1->forceZ -= Fz + li->D2*m1->speedZ; // Fz1[n] = -Fz,Fz1[n] = Fz1[n] - D2 * vz1[n-1] - m2->forceZ += Fz - li->D2*m2->speedZ; // Fz2[n] = Fz,Fz2[n] = Fz2[n] - D2 * vz2[n-1] - li->distance_old = distance; // L[n-1] = L[n] - } - - for (i=0; i<nb_mass; i++) { - t_mass *mi = mass[i]; - // compute new masses position only if mobile = 1 - if (mi->mobile == 1) { - t_float X_new = mi->forceX * mi->invM + 2*mi->posX - mi->posX2; // x[n] =Fx[n]/M+2x[n]-x[n-1] - mi->posX2 = mi->posX; // x[n-2] = x[n-1] - mi->posX = max(min(X_new,Xmax),Xmin); // x[n-1] = x[n] - mi->speedX = mi->posX - mi->posX2; // vx[n] = x[n] - x[n-1] - t_float Y_new = mi->forceY * mi->invM + 2*mi->posY - mi->posY2; // y[n] =Fy[n]/M+2y[n]-y[n-1] - mi->posY2 = mi->posY; // y[n-2] = y[n-1] - mi->posY = max(min(Y_new,Ymax),Ymin); // y[n-1] = y[n] - mi->speedY = mi->posY - mi->posY2; // vy[n] = y[n] - y[n-1] - t_float Z_new = mi->forceZ * mi->invM + 2*mi->posZ - mi->posZ2; // x[n] =Fx[n]/M+2x[n]-x[n-1] - mi->posZ2 = mi->posZ; // z[n-2] = z[n-1] - mi->posZ = max(min(Z_new,Zmax),Zmin); // z[n-1] = z[n] - mi->speedZ = mi->posZ - mi->posZ2; // vz[n] = z[n] - z[n-1] - } - } - - for (i=0; i<nb_mass; i++) { - t_mass *mi = mass[i]; - // clear forces - mi->out_forceX = mi->forceX; - mi->out_forceY = mi->forceY; - mi->out_forceZ = mi->forceZ; - mi->forceX = mi->forceY = mi->forceZ = 0; - } - } - -// -------------------------------------------------------------- MASSES -// ---------------------------------------------------------------------- - void m_mass(int argc,t_atom *argv) - // add a mass - // Id, nbr, mobile, invM, speedX, posX, forceX - { - t_atom sortie[7], aux[2]; - t_float M; - - if (argc != 6) - error("mass : Id mobile mass X Y Z"); - - mass[nb_mass] = new t_mass; // new mass - mass[nb_mass]->Id = GetSymbol(argv[0]); // Id - mass[nb_mass]->mobile = GetInt(argv[1]); // mobile - if (GetFloat(argv[2])==0) - M=1; - else M = GetFloat(argv[2]); - mass[nb_mass]->invM = 1/(M); // 1/M - mass[nb_mass]->speedX = 0; // vx[n] - mass[nb_mass]->posX = GetFloat(argv[3]); // x[n] - mass[nb_mass]->posX2 = GetFloat(argv[3]); // x[n-1] - mass[nb_mass]->forceX = 0; // Fx[n] - mass[nb_mass]->speedY = 0; // vy[n] - mass[nb_mass]->posY = GetFloat(argv[4]); // y[n] - mass[nb_mass]->posY2 = GetFloat(argv[4]); // y[n-1] - mass[nb_mass]->forceY = 0; // Fz[n] - mass[nb_mass]->speedZ = 0; // vz[n] - mass[nb_mass]->posZ = GetFloat(argv[5]); // z[n] - mass[nb_mass]->posZ2 = GetFloat(argv[5]); // z[n-1] - mass[nb_mass]->forceZ = 0; // Fz[n] - mass[nb_mass]->nbr = id_mass; // id number - nb_mass++ ; - id_mass++; - nb_mass = min ( nb_max_mass -1, nb_mass ); - SetFloat((sortie[0]),id_mass-1); - SetSymbol((sortie[1]),GetSymbol(argv[0])); - SetFloat((sortie[2]),mass[nb_mass-1]->mobile); - SetFloat((sortie[3]),M); - SetFloat((sortie[4]),mass[nb_mass-1]->posX); - SetFloat((sortie[5]),mass[nb_mass-1]->posY); - SetFloat((sortie[6]),mass[nb_mass-1]->posZ); - ToOutAnything(1,S_Mass ,7,sortie); - } - - void m_forceX(int argc,t_atom *argv) - { - // add a force to mass(es) named Id or No - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("forceX : Idmass value"); - - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->forceX = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (sym == (*mi)->Id) - (*mi)->forceX = GetFloat(argv[1]); - } - } - - void m_forceY(int argc,t_atom *argv) - { - // add a force to mass(es) named Id or No - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("forceX : Idmass value"); - - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->forceY = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (sym == (*mi)->Id) - (*mi)->forceY = GetFloat(argv[1]); - } - } - - void m_forceZ(int argc,t_atom *argv) - { - // add a force to mass(es) named Id or No - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("forceX : Idmass value"); - - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->forceZ = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (sym == (*mi)->Id) - (*mi)->forceZ = GetFloat(argv[1]); - } - } - - void m_posX(int argc,t_atom *argv) - { - // displace mass(es) named Id to a certain position - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("posX : Id/Nomass value"); - - if (GetFloat(argv[1]) < Xmax && GetFloat(argv[1]) > Xmin) - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->posX = GetFloat(argv[1]); - (*mi)->posX2 = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if (sym == (*mi)->Id) { - (*mi)->posX = GetFloat(argv[1]); - (*mi)->posX2 = GetFloat(argv[1]); - } - } - - void m_posY(int argc,t_atom *argv) - { - // displace mass(es) named Id to a certain position - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("posY : Id/Nomass value"); - - if (GetFloat(argv[1]) < Ymax && GetFloat(argv[1]) > Ymin) - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->posY = GetFloat(argv[1]); - (*mi)->posY2 = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if (sym == (*mi)->Id) { - (*mi)->posY = GetFloat(argv[1]); - (*mi)->posY2 = GetFloat(argv[1]); - } - } - - void m_posZ(int argc,t_atom *argv) - { - // displace mass(es) named Id to a certain position - t_int i; - const t_symbol *sym = GetASymbol(argv[0]); - t_mass **mi; - - if (argc != 2) - error("posY : Id/Nomass value"); - - if (GetFloat(argv[1]) < Zmax && GetFloat(argv[1]) > Zmin) - if (sym ==0) - for (i=0, mi=mass; i<nb_mass; mi++, i++) - { - if (GetInt(argv[0]) == (*mi)->nbr) { - (*mi)->posZ = GetFloat(argv[1]); - (*mi)->posZ2 = GetFloat(argv[1]); - break; - } - } - else - for (i=0, mi=mass; i<nb_mass; mi++, i++) - if (sym == (*mi)->Id) { - (*mi)->posZ = GetFloat(argv[1]); - (*mi)->posZ2 = GetFloat(argv[1]); - } - } - - void m_set_mobile(int argc,t_atom *argv) - { - // set mass No to mobile - t_int i,aux; - t_mass **mi; - - if (argc != 1) - error("setMobile : Idmass"); - - aux = GetInt(argv[0]); - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - if ((*mi)->nbr == aux) - (*mi)->mobile = 1; - } - - } - - void m_set_fixe(int argc,t_atom *argv) - { - // set mass No to fixed - t_int i,aux; - t_mass **mi; - - if (argc != 1) - error("setFixed : Idmass"); - - aux = GetAInt(argv[0]); - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - if ((*mi)->nbr == aux) - (*mi)->mobile = 0; - } - - } - - void m_delete_mass(int argc,t_atom *argv) - { - // Delete mass - t_int i,nb_link_delete=0; - t_atom sortie[7]; - NEWARR(t_atom,aux,nb_link); - t_mass **mi; - t_link **li; - - if (argc != 1) - error("deleteMass : Nomass"); - - // Delete associated links - for (i=0, li=link; i<nb_link;li++, i++) { - if ((*li)->mass1->nbr == GetInt(argv[0]) || (*li)->mass2->nbr == GetInt(argv[0])) { - SetFloat((aux[nb_link_delete]),(*li)->nbr); - nb_link_delete++; - } - } - - for (i=0; i<nb_link_delete;i++) - m_delete_link(1,&aux[i]); - - // Delete mass - for (i=0, mi=mass; i<nb_mass;mi++, i++) - if ((*mi)->nbr == GetInt(argv[0])) { - SetFloat((sortie[0]),(*mi)->nbr); - SetSymbol((sortie[1]),(*mi)->Id); - SetFloat((sortie[2]),(*mi)->mobile); - SetFloat((sortie[3]),1/(*mi)->invM); - SetFloat((sortie[4]),(*mi)->posX); - SetFloat((sortie[5]),(*mi)->posY); - SetFloat((sortie[6]),(*mi)->posZ); - delete (*mi); - (*mi) = mass[nb_mass-1]; // copy last mass indeed - nb_mass--; - ToOutAnything(1,S_Mass_deleted,7,sortie); - break; - } - DELARR(aux); - } - - - void m_Xmax(int argc,t_atom *argv) - { - // set X max - if (argc != 1) - error("Xmax : Value"); - Xmax = GetFloat(argv[0]); - } - - void m_Xmin(int argc,t_atom *argv) - { - // set X min - if (argc != 1) - error("Xmin : Value"); - Xmin = GetFloat(argv[0]); - } - void m_Ymax(int argc,t_atom *argv) - { - // set Y max - if (argc != 1) - error("Ymax : Value"); - Ymax = GetFloat(argv[0]); - } - - void m_Ymin(int argc,t_atom *argv) - { - // set Y min - if (argc != 1) - error("Ymin : Value"); - Ymin = GetFloat(argv[0]); - } - - void m_Zmax(int argc,t_atom *argv) - { - // set maximum Z of all masses - if (argc != 1) - error("Zmax : Value"); - Zmax = GetFloat(argv[0]); - } - - void m_Zmin(int argc,t_atom *argv) - { - // set minimum Z of all masses - if (argc != 1) - error("Zmin : Value"); - Zmin = GetFloat(argv[0]); - } - -// -------------------------------------------------------------- LINKS -// --------------------------------------------------------------------- - void m_link(int argc,t_atom *argv) - // add a link - // Id, *mass1, *mass2, K1, D1, D2, (Lmin,Lmax) - { - t_atom sortie[7], aux[2]; - t_int i; - t_mass *mass1 = NULL; - t_mass *mass2 = NULL; - t_mass **mi; - - if (argc < 6 || argc > 8) - error("link : Id Nomass1 Nomass2 K D1 D2 (Lmin Lmax)"); - - // check for existence of link masses: - for (i=0, mi=mass; i<nb_mass;mi++, i++) - if ((*mi)->nbr==GetInt(argv[1])) // pointer to mass1 - // we found mass1 - mass1 = (*mi); - else if ((*mi)->nbr==GetInt(argv[2])) // pointer to mass2 - // ... and mass2 - mass2 = (*mi); - - if (mass1 and mass2) - { - link[nb_link] = new t_link; // New pointer - link[nb_link]->Id = GetSymbol(argv[0]); // ID - link[nb_link]->mass1 = mass1; // pointer to mass1 - link[nb_link]->mass2 = mass2; // pointer to mass2 - link[nb_link]->K1 = GetFloat(argv[3]); // K1 - link[nb_link]->D1 = GetFloat(argv[4]); // D1 - link[nb_link]->D2 = GetFloat(argv[5]); // D2 - link[nb_link]->longx = link[nb_link]->mass1->posX - link[nb_link]->mass2->posX; // Lx[0] - link[nb_link]->longy = link[nb_link]->mass1->posY - link[nb_link]->mass2->posY; // Ly[0] - link[nb_link]->longz = link[nb_link]->mass1->posZ - link[nb_link]->mass2->posZ; // Lz[0] - link[nb_link]->longueur = sqrt(pow(link[nb_link]->longx,2)+pow(link[nb_link]->longy,2)+pow(link[nb_link]->longz,2));//L[0] - link[nb_link]->nbr = id_link; // id number - link[nb_link]->distance_old = link[nb_link]->longueur; // L[n-1] - switch (argc) { - case 6 : - link[nb_link]->long_max = 32768; - link[nb_link]->long_min = 0; - break; - case 7 : - link[nb_link]->long_min = GetFloat(argv[6]); - link[nb_link]->long_max = 32768; - break; - case 8 : - link[nb_link]->long_min = GetFloat(argv[6]); - link[nb_link]->long_max = GetFloat(argv[7]); - break; - } - nb_link++; - id_link++; - nb_link = min ( nb_max_link -1, nb_link ); - SetFloat((sortie[0]),id_link-1); - SetSymbol((sortie[1]),link[nb_link-1]->Id); - SetFloat((sortie[2]),GetInt(argv[1])); - SetFloat((sortie[3]),GetInt(argv[2])); - SetFloat((sortie[4]),link[nb_link-1]->K1); - SetFloat((sortie[5]),link[nb_link-1]->D1); - SetFloat((sortie[6]),link[nb_link-1]->D2); - ToOutAnything(1,S_Link,7,sortie); - } - else - error("link : Cannot create link: Not all masses for this link have been created yet."); - } - - void m_ilink(int argc,t_atom *argv) - // add interactor link - // Id, Id masses1, Id masses2, K1, D1, D2, (Lmin, Lmax) - { - t_atom aux[2], arglist[8]; - t_int i,j, nbmass1=0, nbmass2=0; - NEWARR(t_int,imass1,nb_mass); - NEWARR(t_int,imass2,nb_mass); - t_symbol *Id1, *Id2; - t_mass **mi; - - if (argc < 6 || argc > 8) - error("ilink : Id Idmass1 Idmass2 K D1 D2 (Lmin Lmax)"); - - Id1 = GetSymbol(argv[1]); - Id2 = GetSymbol(argv[2]); - ToOutAnything(1,S_iLink,0,aux); - - for (i=0, mi=mass; i<nb_mass;mi++, i++) { - if (Id1 == (*mi)->Id) { - imass1[nbmass1]=i; - nbmass1++; - } - if (Id2 == (*mi)->Id) { - imass2[nbmass2]=i; - nbmass2++; - } - } - - for(i=0;i<nbmass1;i++) - for(j=0;j<nbmass2;j++) - if (imass1[i] != imass2[j]) { - SetSymbol((arglist[0]),GetSymbol(argv[0])); - SetFloat((arglist[1]),mass[imass1[i]]->nbr); - SetFloat((arglist[2]),mass[imass2[j]]->nbr); - SetFloat((arglist[3]),GetFloat(argv[3])); - SetFloat((arglist[4]),GetFloat(argv[4])); - SetFloat((arglist[5]),GetFloat(argv[5])); - switch (argc) { - case 7 : - SetFloat(arglist[6],GetFloat(argv[6])); - break; - case 8 : - SetFloat(arglist[6],GetFloat(argv[6])); - SetFloat(arglist[7],GetFloat(argv[7])); - break; - } - m_link(argc,arglist); - } - DELARR(imass1); - DELARR(imass2); - } - - void m_setK(int argc,t_atom *argv) - { - // set rigidity of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setK : IdLink Value"); - - for (i=0, li=link; i<nb_link;li++, i++) - { - if (sym == (*li)->Id) - (*li)->K1 = GetFloat(argv[1]); - } - } - - void m_setD(int argc,t_atom *argv) - { - // set damping of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setD : IdLink Value"); - - for (i=0, li=link; i<nb_link;li++, i++) - { - if (sym == (*li)->Id) - (*li)->D1 = GetFloat(argv[1]); - } - } - - void m_setD2(int argc,t_atom *argv) - { - // set damping of link(s) named Id - t_int i; - const t_symbol *sym = GetSymbol(argv[0]); - t_link **li; - - if (argc != 2) - error("setD2 : IdLink Value"); - - for (i=0, li=link; i<nb_link;li++, i++) - { - if (sym == (*li)->Id) - (*li)->D2 = GetFloat(argv[1]); - } - } - - void m_delete_link(int argc,t_atom *argv) - { - // Delete link - t_int i; - t_atom sortie[7]; - t_link **li; - - if (argc != 1) - error("deleteLink : NoLink"); - - for (i=0, li=link; i<nb_link;li++, i++) - if ((*li)->nbr == GetInt(argv[0])) { - SetFloat((sortie[0]),(*li)->nbr); - SetSymbol((sortie[1]),(*li)->Id); - SetFloat((sortie[2]),(*li)->mass1->nbr); - SetFloat((sortie[3]),(*li)->mass2->nbr); - SetFloat((sortie[4]),(*li)->K1); - SetFloat((sortie[5]),(*li)->D1); - SetFloat((sortie[6]),(*li)->D2); - delete (*li); - (*li)=link[nb_link-1]; // copy last link instead - nb_link--; - ToOutAnything(1,S_Link_deleted,7,sortie); - break; - } - } - - -// -------------------------------------------------------------- GET -// ------------------------------------------------------------------- - void m_get(int argc,t_atom *argv) - // get attributes - { - t_int i,j; - t_symbol *auxarg,*auxarg2, *auxtype; - t_atom sortie[7]; - auxtype = GetSymbol(argv[0]); - auxarg = GetASymbol(argv[1]); //auxarg : & symbol, 0 else - t_mass **mi; - t_link **li; - - if (argc == 1) - { - if (auxtype == S_massesPos)// get all masses positions - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->posX); - SetFloat(sortie[2],(*mi)->posY); - SetFloat(sortie[3],(*mi)->posZ); - ToOutAnything(0,S_massesPos,4,sortie); - } - else if (auxtype == S_massesForces)// get all masses forces - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->out_forceX); - SetFloat(sortie[2],(*mi)->out_forceY); - SetFloat(sortie[3],(*mi)->out_forceZ); - ToOutAnything(0,S_massesForces,4,sortie); - } - else if (auxtype == S_linksPos)// get all links positions - for (i=0, li=link; i<nb_link;li++, i++) - { - SetFloat(sortie[0],(*li)->nbr); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass1->posY); - SetFloat(sortie[3],(*li)->mass1->posZ); - SetFloat(sortie[4],(*li)->mass2->posX); - SetFloat(sortie[5],(*li)->mass2->posY); - SetFloat(sortie[6],(*li)->mass2->posZ); - ToOutAnything(0,S_linksPos,7,sortie); - } - else // get all masses speeds - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->speedX); - SetFloat(sortie[2],(*mi)->speedY); - SetFloat(sortie[3],(*mi)->speedZ); - ToOutAnything(0,S_massesSpeeds,4,sortie); - } - } - else if (auxtype == S_massesPos) // get mass positions - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, mi=mass; i<nb_mass;mi++, i++) - if ((*mi)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->posX); - SetFloat(sortie[2],(*mi)->posY); - SetFloat(sortie[3],(*mi)->posZ); - ToOutAnything(0,S_massesPosNo,4,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->posX); - SetFloat(sortie[2],(*mi)->posY); - SetFloat(sortie[3],(*mi)->posZ); - ToOutAnything(0,S_massesPosId,4,sortie); - } - } - } - } - } - else if (auxtype == S_massesForces) // get mass forces - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, mi=mass; i<nb_mass;mi++, i++) - if ((*mi)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->out_forceX); - SetFloat(sortie[2],(*mi)->out_forceY); - SetFloat(sortie[3],(*mi)->out_forceZ); - ToOutAnything(0,S_massesForcesNo,4,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->out_forceX); - SetFloat(sortie[2],(*mi)->out_forceY); - SetFloat(sortie[3],(*mi)->out_forceZ); - ToOutAnything(0,S_massesForcesId,4,sortie); - } - } - } - } - } - else if (auxtype == S_linksPos) // get links positions - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, li=link; i<nb_link;li++, i++) - if ((*li)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*li)->nbr); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass1->posY); - SetFloat(sortie[3],(*li)->mass1->posZ); - SetFloat(sortie[4],(*li)->mass2->posX); - SetFloat(sortie[5],(*li)->mass2->posY); - SetFloat(sortie[6],(*li)->mass2->posZ); - ToOutAnything(0,S_linksPosNo,7,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, li=link; i<nb_link;li++, i++) - { - if (auxarg2==(*li)->Id) - { - SetSymbol(sortie[0],(*li)->Id); - SetFloat(sortie[1],(*li)->mass1->posX); - SetFloat(sortie[2],(*li)->mass1->posY); - SetFloat(sortie[3],(*li)->mass1->posZ); - SetFloat(sortie[4],(*li)->mass2->posX); - SetFloat(sortie[5],(*li)->mass2->posY); - SetFloat(sortie[6],(*li)->mass2->posZ); - ToOutAnything(0,S_linksPosId,7,sortie); - } - } - } - } - } - else // get mass speeds - { - if (auxarg == 0) // No - { - for (j = 1; j<argc; j++) - for (i=0, mi=mass; i<nb_mass;mi++, i++) - if ((*mi)->nbr==GetInt(argv[j])) - { - SetFloat(sortie[0],(*mi)->nbr); - SetFloat(sortie[1],(*mi)->speedX); - SetFloat(sortie[2],(*mi)->speedY); - SetFloat(sortie[3],(*mi)->speedZ); - ToOutAnything(0,S_massesSpeedsNo,4,sortie); - } - } - else //symbol - { - for (j = 1; j<argc; j++) - { - auxarg2 = GetSymbol(argv[j]); - for (i=0, mi=mass; i<nb_mass;mi++, i++) - { - if (auxarg2==(*mi)->Id) - { - SetSymbol(sortie[0],(*mi)->Id); - SetFloat(sortie[1],(*mi)->speedX); - SetFloat(sortie[2],(*mi)->speedY); - SetFloat(sortie[3],(*mi)->speedZ); - ToOutAnything(0,S_massesSpeedsId,4,sortie); - } - } - } - } - } - - - } - - void m_mass_dumpl() - // List of masses positions on first outlet - { - NEWARR(t_atom,sortie,3*nb_mass); - t_int i; - t_mass **mi; - - for (i=0, mi=mass; i<nb_mass;mi++, i++) { - SetFloat((sortie[3*i]),(*mi)->posX); - SetFloat((sortie[3*i+1]),(*mi)->posY); - SetFloat((sortie[3*i+2]),(*mi)->posZ); - } - ToOutAnything(0, S_massesPosL, 3*nb_mass, sortie); - DELARR(sortie); - } - - void m_force_dumpl() - // List of masses positions on first outlet - { - NEWARR(t_atom,sortie,3*nb_mass); - t_int i; - t_mass **mi; - - for (i=0, mi=mass; i<nb_mass;mi++, i++) { - SetFloat((sortie[3*i]),(*mi)->out_forceX); - SetFloat((sortie[3*i+1]),(*mi)->out_forceY); - SetFloat((sortie[3*i+2]),(*mi)->out_forceZ); - } - ToOutAnything(0, S_massesForcesL, 3*nb_mass, sortie); - DELARR(sortie); - } - - void m_info_dumpl() - // List of masses positions on first outlet - { - t_atom sortie[7]; - t_int i; - t_mass **mi; - t_link **li; - - for (i=0, mi=mass; i<nb_mass;mi++, i++) { - SetFloat((sortie[0]),(*mi)->nbr); - SetSymbol((sortie[1]),(*mi)->Id); - SetFloat((sortie[2]),(*mi)->mobile); - SetFloat((sortie[3]),1/(*mi)->invM); - SetFloat((sortie[4]),(*mi)->posX); - SetFloat((sortie[5]),(*mi)->posY); - SetFloat((sortie[6]),(*mi)->posZ); - ToOutAnything(1, S_Mass, 7, sortie); - } - - for (i=0, li=link; i<nb_link;li++, i++) { - SetFloat((sortie[0]),(*li)->nbr); - SetSymbol((sortie[1]),(*li)->Id); - SetFloat((sortie[2]),(*li)->mass1->nbr); - SetFloat((sortie[3]),(*li)->mass2->nbr); - SetFloat((sortie[4]),(*li)->K1); - SetFloat((sortie[5]),(*li)->D1); - SetFloat((sortie[6]),(*li)->D2); - ToOutAnything(1, S_Link, 7, sortie); - } - - } - -// -------------------------------------------------------------- GLOBAL VARIABLES -// -------------------------------------------------------------------------------- - t_link * link[nb_max_link]; - t_mass * mass[nb_max_mass]; - t_float Xmin, Xmax, Ymin, Ymax, Zmin, Zmax; - int nb_link, nb_mass, id_mass, id_link; - -// -------------------------------------------------------------- SETUP -// --------------------------------------------------------------------- -private: - - // static symbols - const static t_symbol *S_Reset; - const static t_symbol *S_Mass; - const static t_symbol *S_Link; - const static t_symbol *S_iLink; - const static t_symbol *S_Mass_deleted; - const static t_symbol *S_Link_deleted; - const static t_symbol *S_massesPos; - const static t_symbol *S_massesPosNo; - const static t_symbol *S_massesPosId; - const static t_symbol *S_linksPos; - const static t_symbol *S_linksPosNo; - const static t_symbol *S_linksPosId; - const static t_symbol *S_massesForces; - const static t_symbol *S_massesForcesNo; - const static t_symbol *S_massesForcesId; - const static t_symbol *S_massesSpeeds; - const static t_symbol *S_massesSpeedsNo; - const static t_symbol *S_massesSpeedsId; - const static t_symbol *S_massesPosL; - const static t_symbol *S_massesForcesL; - - static void setup(t_classid c) - { - - // --- set up methods (class scope) --- - - - // register a bang method to the default inlet (0) - FLEXT_CADDBANG(c,0,m_bang); - - // set up tagged methods for the default inlet (0) - // the underscore _ after CADDMETHOD indicates that a message tag is used - // no, variable list or anything and all single arguments are recognized automatically, ... - FLEXT_CADDMETHOD_(c,0,"reset",m_reset); - FLEXT_CADDMETHOD_(c,0,"forceX",m_forceX); - FLEXT_CADDMETHOD_(c,0,"forceY",m_forceY); - FLEXT_CADDMETHOD_(c,0,"forceZ",m_forceZ); - FLEXT_CADDMETHOD_(c,0,"posX",m_posX); - FLEXT_CADDMETHOD_(c,0,"Xmax",m_Xmax); - FLEXT_CADDMETHOD_(c,0,"Xmin",m_Xmin); - FLEXT_CADDMETHOD_(c,0,"Ymax",m_Ymax); - FLEXT_CADDMETHOD_(c,0,"Ymin",m_Ymin); - FLEXT_CADDMETHOD_(c,0,"posY",m_posY); - FLEXT_CADDMETHOD_(c,0,"Zmax",m_Zmax); - FLEXT_CADDMETHOD_(c,0,"Zmin",m_Zmin); - FLEXT_CADDMETHOD_(c,0,"posZ",m_posZ); - FLEXT_CADDMETHOD_(c,0,"setK",m_setK); - FLEXT_CADDMETHOD_(c,0,"setD",m_setD); - FLEXT_CADDMETHOD_(c,0,"setD2",m_setD2); - FLEXT_CADDMETHOD_(c,0,"mass",m_mass); - FLEXT_CADDMETHOD_(c,0,"link",m_link); - FLEXT_CADDMETHOD_(c,0,"iLink",m_ilink); - FLEXT_CADDMETHOD_(c,0,"get",m_get); - FLEXT_CADDMETHOD_(c,0,"deleteLink",m_delete_link); - FLEXT_CADDMETHOD_(c,0,"deleteMass",m_delete_mass); - FLEXT_CADDMETHOD_(c,0,"massesPosL",m_mass_dumpl); - FLEXT_CADDMETHOD_(c,0,"infosL",m_info_dumpl); - FLEXT_CADDMETHOD_(c,0,"massesForcesL",m_force_dumpl); - FLEXT_CADDMETHOD_(c,0,"setMobile",m_set_mobile); - FLEXT_CADDMETHOD_(c,0,"setFixed",m_set_fixe); - } - - // for every registered method a callback has to be declared - FLEXT_CALLBACK(m_bang) - FLEXT_CALLBACK(m_mass_dumpl) - FLEXT_CALLBACK(m_info_dumpl) - FLEXT_CALLBACK(m_force_dumpl) - FLEXT_CALLBACK(m_reset) - FLEXT_CALLBACK_V(m_mass) - FLEXT_CALLBACK_V(m_link) - FLEXT_CALLBACK_V(m_ilink) - FLEXT_CALLBACK_V(m_Xmax) - FLEXT_CALLBACK_V(m_Xmin) - FLEXT_CALLBACK_V(m_Ymax) - FLEXT_CALLBACK_V(m_Ymin) - FLEXT_CALLBACK_V(m_Zmax) - FLEXT_CALLBACK_V(m_Zmin) - FLEXT_CALLBACK_V(m_setK) - FLEXT_CALLBACK_V(m_setD) - FLEXT_CALLBACK_V(m_setD2) - FLEXT_CALLBACK_V(m_forceX) - FLEXT_CALLBACK_V(m_forceY) - FLEXT_CALLBACK_V(m_forceZ) - FLEXT_CALLBACK_V(m_posX) - FLEXT_CALLBACK_V(m_posY) - FLEXT_CALLBACK_V(m_posZ) - FLEXT_CALLBACK_V(m_get) - FLEXT_CALLBACK_V(m_delete_link) - FLEXT_CALLBACK_V(m_delete_mass) - FLEXT_CALLBACK_V(m_set_mobile) - FLEXT_CALLBACK_V(m_set_fixe) -}; - - const t_symbol *msd3D::S_Reset = MakeSymbol("Reset"); - const t_symbol *msd3D::S_Mass = MakeSymbol("Mass"); - const t_symbol *msd3D::S_Link = MakeSymbol("Link"); - const t_symbol *msd3D::S_iLink = MakeSymbol("iLink"); - const t_symbol *msd3D::S_Mass_deleted = MakeSymbol("Mass deleted"); - const t_symbol *msd3D::S_Link_deleted = MakeSymbol("Link deleted"); - const t_symbol *msd3D::S_massesPos = MakeSymbol("massesPos"); - const t_symbol *msd3D::S_massesPosNo = MakeSymbol("massesPosNo"); - const t_symbol *msd3D::S_massesPosId = MakeSymbol("massesPosId"); - const t_symbol *msd3D::S_linksPos = MakeSymbol("linksPos"); - const t_symbol *msd3D::S_linksPosNo = MakeSymbol("linksPosNo"); - const t_symbol *msd3D::S_linksPosId = MakeSymbol("linksPosId"); - const t_symbol *msd3D::S_massesForces = MakeSymbol("massesForces"); - const t_symbol *msd3D::S_massesForcesNo = MakeSymbol("massesForcesNo"); - const t_symbol *msd3D::S_massesForcesId = MakeSymbol("massesForcesId"); - const t_symbol *msd3D::S_massesSpeeds = MakeSymbol("massesSpeeds"); - const t_symbol *msd3D::S_massesSpeedsNo = MakeSymbol("massesSpeedsNo"); - const t_symbol *msd3D::S_massesSpeedsId = MakeSymbol("massesSpeedsId"); - const t_symbol *msd3D::S_massesPosL = MakeSymbol("massesPosL"); - const t_symbol *msd3D::S_massesForcesL = MakeSymbol("massesForcesL"); - -// instantiate the class (constructor has a variable argument list) -FLEXT_NEW_V("msd3D",msd3D) - - +MSD("msd3D",msd3D,3) diff --git a/msd3D/package.txt b/msd3D/package.txt index b70eac4..9d8a8db 100644 --- a/msd3D/package.txt +++ b/msd3D/package.txt @@ -1,2 +1,4 @@ -NAME=msd3D
-SRCS=main.cpp
+NAME=msd3D +SRCS=main.cpp +HDRS=../msd.h + |