aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2005-05-02 15:39:24 +0000
committerThomas Grill <xovo@users.sourceforge.net>2005-05-02 15:39:24 +0000
commitbf1bd0b97f46224b8a639303919f191698771684 (patch)
treeff045d30cf8cf40f4bb523dee80c4ff44ab5e9aa
parent08139b3d3bf914933c2e040e559d4a62ded735ea (diff)
generalized 1,2,3 dimensions into templates
log(O(n)) search for symbols and indices many optimizations fixed memory leaks better error reporting dependent on flext 0.5.0 svn path=/trunk/externals/nusmuk/; revision=2882
-rw-r--r--msd.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
+