SkinningMapping.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #ifndef SOFA_COMPONENT_MAPPING_SKINNINGMAPPING_INL
00026 #define SOFA_COMPONENT_MAPPING_SKINNINGMAPPING_INL
00027 
00028 #include <sofa/component/mapping/SkinningMapping.h>
00029 #include <sofa/defaulttype/VecTypes.h>
00030 #include <sofa/defaulttype/RigidTypes.h>
00031 #include <sofa/helper/io/MassSpringLoader.h>
00032 #include <sofa/helper/io/SphereLoader.h>
00033 #include <sofa/helper/io/Mesh.h>
00034 #include <sofa/helper/gl/template.h>
00035 #include <sofa/core/componentmodel/behavior/MechanicalMapping.inl>
00036 #include <sofa/core/componentmodel/behavior/MechanicalState.h>
00037 #include <string>
00038 #include <iostream>
00039         
00040 using std::cerr;
00041 using std::endl;
00042 
00043 
00044 
00045 namespace sofa
00046 {
00047 
00048 namespace component
00049 {
00050 
00051 namespace mapping
00052 {
00053 
00054 using namespace sofa::defaulttype;
00055 
00056 template <class BasicMapping>
00057 class SkinningMapping<BasicMapping>::Loader : public helper::io::MassSpringLoader, public helper::io::SphereLoader
00058 {
00059   public:
00060     SkinningMapping<BasicMapping>* dest;
00061     Loader(SkinningMapping<BasicMapping>* dest) : dest(dest) {}
00062     virtual void addMass(SReal /*px*/, SReal /*py*/, SReal /*pz*/, SReal, SReal, SReal, SReal, SReal, bool, bool)
00063     {
00064         /*Coord c;
00065         Out::DataTypes::set(c,px,py,pz);
00066         dest->initPos.push_back(c); //Coord((Real)px,(Real)py,(Real)pz));*/
00067     }
00068     virtual void addSphere(SReal /*px*/, SReal /*py*/, SReal /*pz*/, SReal)
00069     {
00070         /*Coord c;
00071         Out::DataTypes::set(c,px,py,pz);
00072         dest->initPos.push_back(c); //Coord((Real)px,(Real)py,(Real)pz));*/
00073     }
00074 };
00075 
00076 template <class BasicMapping>
00077 void SkinningMapping<BasicMapping>::load(const char * /*filename*/)
00078 {
00079  /*   initPos.resize(0);
00080     
00081     if (strlen(filename)>4 && !strcmp(filename+strlen(filename)-4,".xs3"))
00082     {
00083         Loader loader(this);
00084         loader.helper::io::MassSpringLoader::load(filename);
00085     }
00086     else
00087     if (strlen(filename)>4 && !strcmp(filename+strlen(filename)-4,".sph"))
00088     {
00089         Loader loader(this);
00090         loader.helper::io::SphereLoader::load(filename);
00091     }
00092     else if (strlen(filename)>0)
00093     { // Default to mesh loader
00094         helper::io::Mesh* mesh = helper::io::Mesh::Create(filename);
00095         if (mesh!=NULL)
00096         {
00097             initPos.resize(mesh->getVertices().size());
00098             for (unsigned int i=0;i<mesh->getVertices().size();i++)
00099             {
00100                 Out::DataTypes::set(initPos[i].getCenter(), mesh->getVertices()[i][0], mesh->getVertices()[i][1], mesh->getVertices()[i][2]);
00101             }
00102             delete mesh;
00103         }
00104     }*/
00105 }
00106 
00107 template <class BasicMapping>
00108 void SkinningMapping<BasicMapping>::init()
00109 {
00110     if (this->initPos.empty() && this->toModel!=NULL && computeWeights==true && coefs.getValue().size()==0)
00111     {
00112         VecCoord& xto = *this->toModel->getX();
00113         VecInCoord& xfrom = *this->fromModel->getX();
00114         initPos.resize(nbRefs.getValue()*xto.size());
00115 
00116         //init the arrays
00117         sofa::helper::vector<unsigned int> m_reps = repartition.getValue();
00118         m_reps.clear();
00119         m_reps.resize(nbRefs.getValue()*xto.size());
00120         sofa::helper::vector<double> m_coefs = coefs.getValue();
00121         m_coefs.clear();
00122         m_coefs.resize(nbRefs.getValue()*xto.size());
00123 
00124         Coord posTo;
00125 
00126         double * minDists = new double[nbRefs.getValue()];
00127         unsigned int * minInds = new unsigned int[nbRefs.getValue()];
00128 
00129         for (unsigned int i=0;i<xto.size();i++){
00130             posTo = xto[i];
00131             for (unsigned int h=0 ; h<nbRefs.getValue() ; h++)
00132                 minDists[h] = 9999999. ;
00133 
00134             //search the nbRefs nearest "from" dofs of each "to" point
00135             for (unsigned int j=0;j<xfrom.size();j++){
00136                 Real dist2 = (posTo - xfrom[j].getCenter()).norm();
00137 
00138                 unsigned int k=0;
00139                 while(k<nbRefs.getValue()){
00140                     if( dist2 < minDists[k] ){
00141                         for(unsigned int m=nbRefs.getValue()-1 ; m>k ; m--){
00142                             minDists[m] = minDists[m-1];
00143                             minInds[m] = minInds[m-1];
00144                         }
00145                         minDists[k] = dist2;
00146                         minInds[k] = j;
00147                         k=nbRefs.getValue();
00148                     }
00149                     k++;
00150                 }
00151             }
00152 
00153             //then compute the coefficients from the inverse distance (coef = 1/d)
00154             for (unsigned int k=0;k<nbRefs.getValue();k++){
00155                 minDists[k] = 1 / minDists[k];
00156             }
00157             //minDists.normalize();
00158             //normalize the coefs vector such as the sum is equal to 1
00159             double norm=0.0;
00160             for (unsigned int h=0 ; h<nbRefs.getValue(); h++)
00161                 norm += minDists[h]*minDists[h];
00162             norm = helper::rsqrt(norm);
00163 
00164             for (unsigned int g=0 ; g<nbRefs.getValue(); g++)
00165                 minDists[g] /= norm;
00166 
00167             for (unsigned int m=0;m<nbRefs.getValue();m++){
00168                 m_coefs[nbRefs.getValue()*i+m] = minDists[m]*minDists[m];
00169                 m_reps[nbRefs.getValue()*i+m] = minInds[m];
00170 
00171                 initPos[nbRefs.getValue()*i+m].getCenter() = xfrom[minInds[m]].getOrientation().inverseRotate(posTo - xfrom[minInds[m]].getCenter());
00172                 initPos[nbRefs.getValue()*i+m].getOrientation() = xfrom[minInds[m]].getOrientation();
00173             }
00174         }
00175         repartition.setValue(m_reps);
00176         coefs.setValue(m_coefs);
00177         delete [] minInds;
00178         delete [] minDists;
00179     }
00180     else if (computeWeights == false || coefs.getValue().size()!=0)
00181     {
00182         sofa::helper::vector<unsigned int> m_reps = repartition.getValue();
00183         sofa::helper::vector<double> m_coefs = coefs.getValue();
00184         VecCoord& xto = *this->toModel->getX();
00185         VecInCoord& xfrom = *this->fromModel->getX();
00186         initPos.resize(nbRefs.getValue()*xto.size());
00187         Coord posTo;
00188 
00189         for (unsigned int i=0;i<xto.size();i++){
00190             posTo = xto[i];
00191             for (unsigned int m=0;m<nbRefs.getValue();m++){
00192                 initPos[nbRefs.getValue()*i+m].getCenter() = xfrom[m_reps[nbRefs.getValue()*i+m]].getOrientation().inverseRotate(posTo - xfrom[m_reps[nbRefs.getValue()*i+m]].getCenter());
00193                 initPos[nbRefs.getValue()*i+m].getOrientation() = xfrom[m_reps[nbRefs.getValue()*i+m]].getOrientation();
00194             }
00195         }
00196     }
00197 
00198     this->BasicMapping::init();
00199 }
00200 
00201 template <class BasicMapping>
00202 void SkinningMapping<BasicMapping>::clear()
00203 {
00204     this->initPos.clear();
00205 }
00206 
00207 
00208 template <class BasicMapping>
00209 void SkinningMapping<BasicMapping>::setWeightCoefs(sofa::helper::vector<double> &weights)
00210 {
00211     sofa::helper::vector<double> * m_coefs = coefs.beginEdit();
00212     m_coefs->clear();
00213     m_coefs->insert(m_coefs->begin(), weights.begin(), weights.end() );
00214     coefs.endEdit();
00215 }
00216 
00217 template <class BasicMapping>
00218 void SkinningMapping<BasicMapping>::setRepartition(sofa::helper::vector<unsigned int> &rep)
00219 {
00220     sofa::helper::vector<unsigned int> * m_reps = repartition.beginEdit();
00221     m_reps->clear();
00222     m_reps->insert(m_reps->begin(), rep.begin(), rep.end() );;
00223     repartition.endEdit();
00224 }
00225 
00226 
00227 template <class BasicMapping>
00228 void SkinningMapping<BasicMapping>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
00229 {
00230     const sofa::helper::vector<unsigned int>& m_reps = repartition.getValue();
00231     const sofa::helper::vector<double>& m_coefs = coefs.getValue();
00232     rotatedPoints.resize(initPos.size());
00233     out.resize(initPos.size()/nbRefs.getValue());
00234 
00235     for (unsigned int i=0 ; i<out.size(); i++)
00236     {
00237         out[i] = Coord();
00238         for (unsigned int m=0 ; m<nbRefs.getValue(); m++)
00239         {
00240             translation = in[m_reps[nbRefs.getValue()*i+m] ].getCenter();
00241             Quat relativeRot = initPos[nbRefs.getValue()*i+m].getOrientation().inverse() * in[m_reps[nbRefs.getValue()*i+m] ].getOrientation();
00242             //in[repartition[nbRefs.getValue()*i+m].getValue()].writeRotationMatrix(rotation);
00243             relativeRot.toMatrix(rotation);
00244             rotatedPoints[nbRefs.getValue()*i+m] = rotation * (initPos[nbRefs.getValue()*i+m].getCenter());
00245 
00246             out[i] += initPos[nbRefs.getValue()*i+m].getOrientation().rotate(rotatedPoints[nbRefs.getValue()*i+m] * m_coefs[nbRefs.getValue()*i+m]);
00247             out[i] += translation * m_coefs[nbRefs.getValue()*i+m];
00248         }
00249     }
00250 }
00251 
00252 template <class BasicMapping>
00253 void SkinningMapping<BasicMapping>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
00254 {
00255     const sofa::helper::vector<unsigned int>& m_reps = repartition.getValue();
00256     const sofa::helper::vector<double>& m_coefs = coefs.getValue();
00257 
00258     Deriv v,omega;
00259     out.resize(initPos.size()/nbRefs.getValue());
00260     
00261     for(unsigned int i=0;i<out.size();i++)
00262     {
00263         out[i] = Deriv();
00264         for (unsigned int m=0 ; m<nbRefs.getValue(); m++)
00265         {
00266             v = in[m_reps[nbRefs.getValue()*i+m]].getVCenter();
00267             omega = in[m_reps[nbRefs.getValue()*i+m]].getVOrientation();
00268             out[i] +=  (v - cross(rotatedPoints[nbRefs.getValue()*i+m],omega)) * m_coefs[nbRefs.getValue()*i+m];
00269         }
00270     }
00271 }
00272 
00273 
00274 template <class BasicMapping>
00275 void SkinningMapping<BasicMapping>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
00276 {
00277     const sofa::helper::vector<unsigned int>& m_reps = repartition.getValue();
00278     const sofa::helper::vector<double>& m_coefs = coefs.getValue();
00279 
00280     Deriv v,omega;
00281     for(unsigned int i=0;i<in.size();i++)
00282     {
00283         for (unsigned int m=0 ; m<nbRefs.getValue(); m++)
00284         {
00285             Deriv f = in[i];
00286             v = f;
00287             omega = cross(rotatedPoints[nbRefs.getValue()*i+m],f);
00288             out[m_reps[nbRefs.getValue()*i+m] ].getVCenter() += v * m_coefs[nbRefs.getValue()*i+m];
00289             out[m_reps[nbRefs.getValue()*i+m] ].getVOrientation() += omega * m_coefs[nbRefs.getValue()*i+m];
00290         }
00291     }
00292     
00293 }
00294 
00295 
00296 template <class BasicMapping>
00297 void SkinningMapping<BasicMapping>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
00298 {
00299     const sofa::helper::vector<unsigned int>& m_reps = repartition.getValue();
00300     const sofa::helper::vector<double>& m_coefs = coefs.getValue();
00301     const unsigned int nbr = nbRefs.getValue();
00302     const unsigned int nbi = this->fromModel->getX()->size();
00303     Deriv omega;
00304     typename In::VecDeriv v;
00305     sofa::helper::vector<bool> flags;
00306     int outSize = out.size();
00307     out.resize(in.size() + outSize); // we can accumulate in "out" constraints from several mappings
00308     for(unsigned int j=0;j<in.size();j++)
00309     {
00310         v.clear();
00311         v.resize(nbi);
00312         flags.clear();
00313         flags.resize(nbi);
00314         for (unsigned int id=0;id<in[0].size();++id)
00315         {
00316             unsigned int i = in[0][id].index;
00317             Deriv f = in[0][id].data;
00318             for (unsigned int m=0 ; m<nbr; m++)
00319             {
00320                 omega = cross(rotatedPoints[nbr*i+m],f);
00321                 flags[m_reps[nbr*i+m] ] = true;
00322                 v[m_reps[nbr*i+m] ].getVCenter() += f * m_coefs[nbr*i+m];
00323                 v[m_reps[nbr*i+m] ].getVOrientation() += omega * m_coefs[nbr*i+m];
00324             }
00325         }
00326         out[outSize+j].reserve(nbi);
00327         for (unsigned int i=0 ; i<nbi; i++)
00328         {
00329             //if (!(v[i] == typename In::Deriv()))
00330             if (flags[i])
00331                 out[outSize+j].push_back(typename In::SparseDeriv(i,v[i]));
00332         }
00333     }
00334 }
00335 
00336 template <class BasicMapping>
00337 void SkinningMapping<BasicMapping>::draw()
00338 {
00339     if (!this->getShow()) return;
00340     glDisable (GL_LIGHTING);
00341     glPointSize(1);
00342     glColor4f (1,1,0,1);
00343     glBegin (GL_LINES);
00344 
00345     const typename Out::VecCoord& xOut = *this->toModel->getX();
00346     const typename In::VecCoord& xIn = *this->fromModel->getX();
00347     sofa::helper::vector<unsigned int> m_reps = repartition.getValue();
00348     sofa::helper::vector<double> m_coefs = coefs.getValue();
00349 
00350     for (unsigned int i=0; i<xOut.size(); i++)
00351     {
00352         for (unsigned int m=0 ; m<nbRefs.getValue(); m++)
00353         {
00354             if(m_coefs[nbRefs.getValue()*i+m] > 0.0){
00355                             glColor4d (m_coefs[nbRefs.getValue()*i+m],m_coefs[nbRefs.getValue()*i+m],0,1);
00356                             helper::gl::glVertexT(xIn[m_reps[nbRefs.getValue()*i+m] ].getCenter());
00357                 helper::gl::glVertexT(xOut[i]);
00358             }
00359         }
00360     }
00361     glEnd();
00362 }
00363 
00364 } // namespace mapping
00365 
00366 } // namespace component
00367 
00368 } // namespace sofa
00369 
00370 #endif

Generated on Sun Nov 23 03:34:19 2008 for Sofa by  doxygen 1.5.7.1