SkinningMapping.inl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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 , SReal , SReal , SReal, SReal, SReal, SReal, SReal, bool, bool)
00063 {
00064
00065
00066
00067 }
00068 virtual void addSphere(SReal , SReal , SReal , SReal)
00069 {
00070
00071
00072
00073 }
00074 };
00075
00076 template <class BasicMapping>
00077 void SkinningMapping<BasicMapping>::load(const char * )
00078 {
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
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
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
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
00154 for (unsigned int k=0;k<nbRefs.getValue();k++){
00155 minDists[k] = 1 / minDists[k];
00156 }
00157
00158
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
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);
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
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 }
00365
00366 }
00367
00368 }
00369
00370 #endif