aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--msd.h987
-rwxr-xr-xmsd/main.cpp924
-rw-r--r--msd/package.txt6
-rwxr-xr-xmsd2D/main.cpp1066
-rw-r--r--msd2D/package.txt6
-rwxr-xr-xmsd3D/main.cpp1127
-rw-r--r--msd3D/package.txt6
7 files changed, 1005 insertions, 3117 deletions
diff --git a/msd.h b/msd.h
new file mode 100644
index 0000000..3964cdb
--- /dev/null
+++ b/msd.h
@@ -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
+