Skinned.cpp

Go to the documentation of this file.
00001 
00002 #include <Skinned.h>
00003 
00004 
00005 Skinned::Skinned():mesh(NULL),deformed_mesh(NULL),skeleton(NULL),deformed_skeleton(NULL)
00006 {}
00007 
00008 Skinned::Skinned(const Skinned& )
00009 {}
00010 
00011 Skinned::~Skinned()
00012 {}
00013 
00014 
00015 
00016 
00017 
00018 
00019 Skeleton *Skinned::get_skeleton()
00020 {return skeleton;}
00021 
00022 
00023 Mesh_object *Skinned::get_mesh()
00024 {return mesh;}
00025 
00026 
00027 
00028 int Skinned::set_skeleton(Skeleton *_skeleton)
00029 {skeleton = _skeleton;return 0;}
00030 int Skinned::set_deformed_skeleton(Skeleton *_skeleton)
00031 {deformed_skeleton = _skeleton;return 0;}
00032 
00033 int Skinned::set_mesh(Mesh_object *_mesh)
00034 {mesh = _mesh;return 0;}
00035 int Skinned::set_deformed_mesh(Mesh_object *_mesh)
00036 {deformed_mesh = _mesh;return 0;}
00037 
00038 int Skinned::size_weight()
00039 {
00040   return weight.size();
00041 }
00042 
00043 int Skinned::add_weight(double w)
00044 {
00045   weight.push_back(w);
00046   return 0;
00047 }
00048 
00049 int Skinned::set_weight(int k_index, double value)
00050 {
00051   if(k_index<0 || k_index>=size_weight())
00052     {printf("Error in set_weight in Skinned, k_index[%d] is not correct\n",k_index);exit(-1);}
00053 
00054   weight[k_index] = value;
00055   return 0;
00056 
00057 }
00058 
00059 double Skinned::get_weight(int k_index)
00060 {
00061   if(k_index<0 || k_index>=size_weight())
00062     {printf("Error in get_weight in Skinned, k_index[%d] is not correct\n",k_index);exit(-1);}
00063 
00064   return weight[k_index];
00065 
00066 }
00067 
00068 int Skinned::size_index_weight()
00069 {return index_weight.size();}
00070 
00071 int Skinned::size_index_weight(int k_index)
00072 {
00073   if(k_index<0 || k_index>=(int)index_weight.size())
00074     {printf("Error k_index too large in size_index_weight in Skinned\n");exit(-1);}
00075 
00076   return index_weight[k_index].size();
00077 }
00078 
00079 int Skinned::set_size_index_weight(int size)
00080 {index_weight.resize(size);return 0;}
00081 int Skinned::get_size_index_weight(int k_vertex)
00082 {
00083   if(k_vertex<0 || k_vertex>(int)index_weight.size())
00084     {printf("Error k_vertex[%d] is too large compared to index_weight.size()[%d] in get_size_index_weight in Skinned\n",k_vertex,index_weight.size());exit(-1);}
00085   return index_weight[k_vertex].size();
00086 
00087 }
00088 int Skinned::set_size_index_weight(int k_index,int size)
00089 {index_weight[k_index].resize(size);return 0;}
00090 
00091 int Skinned::add_index_weight(int k_index,int index)
00092 {
00093   if(k_index<0 || k_index>=(int)index_weight.size())
00094     {printf("Error k_index too large in add_index_weight in Skinned\n");exit(-1);}
00095   index_weight[k_index].add(index);
00096   return 0;
00097 }
00098 
00099 int Skinned::add_index_weight(int k_vertex,std::vector <int>& index)
00100 {
00101   if(k_vertex<0 || k_vertex>=(int)index_weight.size())
00102     {printf("Error k_vertex too large in add_index_weight in Skinned\n");exit(-1);}
00103   index_weight[k_vertex].add(index);
00104   return 0;
00105 }
00106 
00107 int Skinned::set_index_weight(int k_vertex,int k_index,int _index_weight)
00108 {
00109   if(k_index<0 || k_index>=(int)index_weight.size())
00110     {printf("Error k_index too large in set_index_weight in Skinned\n");exit(-1);}
00111   index_weight[k_vertex][k_index]=_index_weight;
00112   return 0;
00113 }
00114 int Skinned::get_index_weight(int k_vertex,int k_index)
00115 {
00116   if(k_vertex<0 || k_vertex>=(int)index_weight.size())
00117     {printf("Error k_vertex too large in get_index_weight in Skinned\n");exit(-1);}
00118 
00119   return index_weight[k_vertex][k_index];
00120 }
00121 
00122 
00123 
00124 
00125 
00126 int Skinned::size_index_joint()
00127 {return index_joint.size();}
00128 
00129 int Skinned::size_index_joint(int k_index)
00130 {
00131   if(k_index<0 || k_index>=(int)index_joint.size())
00132     {printf("Error k_index too large in size_index_joint in Skinned\n");exit(-1);}
00133 
00134   return index_joint[k_index].size();
00135 }
00136 
00137 int Skinned::set_size_index_joint(int size)
00138 {index_joint.resize(size);return 0;}
00139 
00140 int Skinned::set_size_index_joint(int k_index,int size)
00141 {index_joint[k_index].resize(size);return 0;}
00142 
00143 int Skinned::add_index_joint(int k_index,int index)
00144 {
00145   if(k_index<0 || k_index>=(int)index_joint.size())
00146     {printf("Error k_index too large in add_index_joint in Skinned\n");exit(-1);}
00147   index_joint[k_index].add(index);
00148   return 0;
00149 }
00150 
00151 int Skinned::add_index_joint(int k_vertex,std::vector <int>& index)
00152 {
00153   if(k_vertex<0 || k_vertex>=(int)index_joint.size())
00154     {printf("Error k_vertex too large in add_index_joint in Skinned\n");exit(-1);}
00155   index_joint[k_vertex].add(index);
00156   return 0;
00157 }
00158 
00159 int Skinned::set_index_joint(int k_vertex,int k_index,int _index_joint)
00160 {
00161   if(k_index<0 || k_index>=(int)index_joint.size())
00162     {printf("Error k_index too large in set_index_joint in Skinned\n");exit(-1);}
00163   index_joint[k_vertex][k_index]=_index_joint;
00164   return 0;
00165 }
00166 int Skinned::get_index_joint(int k_vertex,int k_index)
00167 {
00168   if(k_vertex<0 || k_vertex>=(int)index_joint.size())
00169     {printf("Error k_vertex too large in get_index_joint in Skinned\n");exit(-1);}
00170 
00171   return index_joint[k_vertex][k_index];
00172 }
00173 
00174 
00175 
00176 
00177 int Skinned::fill_vertex_depending_on_bone()
00178 {
00179 
00180   int N_total_bones = skeleton->get_N_joint();
00181   vertex_depending_on_bone.resize(0);
00182   if(N_total_bones>0 && N_total_bones<1000)
00183     vertex_depending_on_bone.resize(N_total_bones);
00184   else
00185     {printf("N_total_bone [%d] is not correct in fill_vertex_depending_on_bone in Mesh\n",N_total_bones);exit(-1);};
00186 
00187   if((int)index_weight.size()!=mesh->get_vertex_number() || (int)index_joint.size()!=mesh->get_vertex_number())
00188     {printf("Error index_weight size[%d] or index_joint size[%d] are not equal to the number of vertex [%d]\n",index_weight.size(),index_joint.size(),mesh->get_vertex_number());exit(-1);}
00189 
00190 
00191 
00192 
00193   int k_vertex=0;
00194   int i_bone=0;
00195   int k_weight_dependencies=0;
00196   float current_weight=0.0f;
00197   float epsilon=0.00001;
00198   double verif_sum_one=0.0;
00199   for(k_vertex=0;k_vertex<mesh->get_vertex_number();k_vertex++)
00200     {
00201       verif_sum_one=0.0;
00202       for(k_weight_dependencies=0;k_weight_dependencies<index_weight[k_vertex].size();k_weight_dependencies++)
00203         {
00204 
00205 
00206           i_bone = get_index_joint(k_vertex,k_weight_dependencies);
00207           current_weight = get_weight(k_vertex,k_weight_dependencies);
00208           verif_sum_one += current_weight;
00209 
00210           
00211           if(current_weight>epsilon)
00212           if(i_bone>=0 && i_bone<N_total_bones)
00213             vertex_depending_on_bone[i_bone].add(k_vertex);
00214           else
00215             {printf("Error in fill_vertex_depending_on_bone in Mesh, i_bone[%d] is not correct\n",i_bone);exit(-1);}
00216 
00217         }
00218       if(fabs(verif_sum_one-1.0)>0.001)
00219         {printf("Erreur in fill_vertex_depending_on_bone in skinned, skinning weights does not summed up to one [k_vertex=%d]\n",k_vertex);exit(-1);}
00220      }
00221 
00222 
00223 
00224 
00225 
00226   return 0;
00227 
00228 }
00229 
00230 double Skinned::get_weight(int k_vertex,int k_index)
00231 {
00232   if(k_vertex<0 || k_vertex>(int)index_weight.size())
00233     {printf("Error k_vertex[%d] is not correct for index_weight.size [%d] in get_weight in Skinned\n",k_vertex,index_weight.size());exit(-1);}
00234   int k_index_weight = index_weight[k_vertex][k_index];
00235   return get_weight(k_index_weight);
00236 }
00237 int Skinned::set_weight(int k_vertex,int k_index_bone,double value)
00238 {
00239   int k_index_weight = get_index_weight(k_vertex,k_index_bone);
00240   set_weight(k_index_weight,value);
00241   return 0;
00242 }
00243 
00244 int Skinned::get_number_of_vertex_depending_on_bone(int k_bone)
00245 {
00246   if(k_bone<0 || k_bone>=(int)vertex_depending_on_bone.size())
00247     {printf("Error k_bone [%d] is not correct with vertex_depending_on_bone.size() [%d] in get_number_of_vertex_depending_on_bone in Skinned\n",k_bone,vertex_depending_on_bone.size());exit(-1);}
00248 
00249   return vertex_depending_on_bone[k_bone].size();
00250 }
00251 
00252 int Skinned::get_index_vertex_depending_on_bone(int k_bone,int k_index)
00253 {
00254   if(k_bone<0 || k_bone>=(int)vertex_depending_on_bone.size())
00255     {printf("Error k_bone [%d] is not correct with vertex_depending_on_bone.size() [%d] in get_index_vertex_depending_on_bone in Skinned\n",k_bone,vertex_depending_on_bone.size());exit(-1);}
00256   
00257   return vertex_depending_on_bone[k_bone][k_index];
00258 
00259 }
00260 
00261 
00262 
00263 int Skinned::skinning()
00264 {
00265   if(deformed_mesh->get_vertex_number()!=mesh->get_vertex_number())
00266     *deformed_mesh = *mesh;
00267   if((deformed_skeleton->get_N_joint()) != (skeleton->get_N_joint()))
00268     *deformed_skeleton = *skeleton;
00269 
00270 
00271   Joint *current = NULL;
00272   int k_vertex=0;
00273   int k_index_vertex=0;
00274   int k_joint=0;
00275   int N_joint=skeleton->get_N_joint();
00276   double current_weight=0.0;
00277 
00278   std::vector <Matrix> vector_T;
00279   vector_T.resize(mesh->get_vertex_number());
00280   for(int k=0;k<mesh->get_vertex_number();k++)
00281     vector_T[k].set_zero();
00282   Matrix T;
00283 
00284 
00285 
00286 
00287   for(k_joint=0;k_joint<N_joint;k_joint++)
00288     {
00289       current = deformed_skeleton->get_joint(k_joint);
00290       T = current->get_T();
00291 
00292       
00293 
00294       for(k_index_vertex=0;k_index_vertex<get_number_of_vertex_depending_on_bone(k_joint);k_index_vertex++)
00295         {
00296           k_vertex = get_index_vertex_depending_on_bone(k_joint,k_index_vertex);
00297           current_weight = get_weight(k_vertex,k_joint);
00298 
00299           vector_T[k_vertex] += (current_weight*T);
00300         }
00301     }
00302 
00303 
00304   V_3D current_vertex;
00305   V_3D current_normal;
00306   for(k_vertex=0;k_vertex<mesh->get_vertex_number();k_vertex++)
00307     {
00308       current_vertex = mesh->get_vertex_v3d(k_vertex);
00309       current_vertex = vector_T[k_vertex]*current_vertex;
00310       deformed_mesh->set_vertex(k_vertex,current_vertex);
00311 
00312       current_normal = mesh->get_vertex_normal(k_vertex);
00313       current_normal = (vector_T[k_vertex].get_rotation_part())*current_normal;
00314       current_normal = current_normal/current_normal.norm();
00315       deformed_mesh->set_vertex_normal(k_vertex,current_normal);
00316     }
00317   return 0;
00318 
00319 }
00320 
00321 int Skinned::check_integrity_skinning()
00322 {
00323 
00324   printf("\n\n[N weight vector %d elements]\n",weight.size());
00325   printf("[N_index_weight %d elements (N_vertex = %d)]\n",index_weight.size(),mesh->get_vertex_number());
00326   printf("[N_index_joint %d elements (N_vertex = %d)]\n",index_joint.size(),mesh->get_vertex_number());
00327 
00328   int k=0;
00329   int k2=0;
00330   for(k=0;k<(int)index_weight.size();k++)
00331     {
00332       for(k2=0;k2<index_weight[k].size();k2++)
00333         {
00334           if(index_weight[k][k2]<0 || index_weight[k][k2]>=(int)weight.size())
00335             {printf("Error index_weight[%d][%d] is too large [%d] compared to weight vector size(%d]\n",k,k2,index_weight[k][k2],weight.size());exit(-1);}
00336 
00337           if(index_joint[k][k2]<0 || index_joint[k][k2]>=(int)skeleton->get_N_joint())
00338             {printf("Error index_joint[%d][%d] is too large [%d] compared to the number of joints (%d]\n",k,k2,index_joint[k][k2],skeleton->get_N_joint());exit(-1);}       
00339         }
00340     }
00341   
00342   int k_vertex;
00343   printf("[%d N_vertex_depending_on_bone (N_bones = %d)]\n",vertex_depending_on_bone.size(),skeleton->get_N_joint());
00344   for(k=0;k<(int)vertex_depending_on_bone.size();k++)
00345     {
00346       //printf("[bone:%d (%s) dependencies:%d]\n",k,skeleton->get_joint(k)->get_name(),get_number_of_vertex_depending_on_bone(k));
00347       for(k2=0;k2<get_number_of_vertex_depending_on_bone(k);k2++)
00348         {
00349           k_vertex = get_index_vertex_depending_on_bone(k,k2);
00350           if(k_vertex<0 || k_vertex>=mesh->get_vertex_number())
00351             {printf("Error for bone %d, index %d, k_vertex[%d] is too large compared to mesh size [%d]\n",k,k2,k_vertex,mesh->get_vertex_number());exit(-1);}
00352 
00353         }
00354     }
00355   
00356 
00357   printf("[Check Skinned integrity OK]\n\n");
00358 
00359   
00360 
00361   return 0;
00362 }
00363 
00364 
00365 int Skinned::set_weight(std::vector <double>& _weight)
00366 {
00367   weight.resize(0);
00368   weight.resize(_weight.size());
00369   int k=0;
00370   for(k=0;k<(int)_weight.size();k++)
00371     weight[k] = _weight[k];
00372   return 0;
00373 }
00374 
00375 int Skinned::set_index_joint(std::vector <int_vector>& _index_joint)
00376 {
00377   index_joint.resize(0);
00378   index_joint.resize(_index_joint.size());
00379   int k=0;
00380   for(k=0;k<(int)_index_joint.size();k++)
00381     index_joint[k] = _index_joint[k];
00382   return 0;
00383 }
00384 
00385 int Skinned::set_index_weight(std::vector <int_vector>& _index_weight)
00386 {
00387   index_weight.resize(0);
00388   index_weight.resize(_index_weight.size());
00389   int k=0;
00390   for(k=0;k<(int)_index_weight.size();k++)
00391     index_weight[k] = _index_weight[k];
00392   return 0;
00393 }
00394 
00395 Skeleton *Skinned::get_deformed_skeleton()
00396 {
00397   return deformed_skeleton;
00398 }
00399 
00400 Mesh_object *Skinned::get_deformed_mesh()
00401 {
00402   return deformed_mesh;
00403 }
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 double Skinned::get_min_distance_to_any_bone(int k_vertex)
00412 {
00413   int k_bone=0;
00414   double min_distance=9999;
00415   double current_distance=0;
00416   for(k_bone=0;k_bone<skeleton->get_N_joint();k_bone++)
00417     {
00418       current_distance = get_vertex_to_bone_distance(k_vertex,k_bone);
00419       if(min_distance>current_distance)
00420         min_distance=current_distance;
00421     }
00422   
00423   return min_distance;
00424 }
00425 
00426 double Skinned::get_vertex_to_bone_distance(int k_vertex,int k_bone)
00427 {
00428   Joint *current = NULL;
00429   Joint *son = NULL;
00430   int k_son=0;
00431 
00432   V_3D x,b1,b2,u1,u2;
00433   V_3D closest;
00434 
00435   x = mesh->get_vertex_v3d(k_vertex);
00436   b1 = skeleton->get_world_position_of_bone(k_bone);
00437   u1 = x-b1;
00438 
00439   current = skeleton->get_joint(k_bone);
00440   double projection=0.0;
00441   double distance=0.0;
00442   double min_distance=99999;
00443   for(k_son=0;k_son<current->get_N_son();k_son++)
00444     {
00445       son = current->get_son(current->get_N_son()-k_son-1);
00446       b2 = skeleton->get_world_position_of_bone(son->get_access_number());
00447       u2 = b2-b1;
00448 
00449       projection = u1.dot(u2)/u2.dot(u2);
00450       if(projection<0)
00451         closest=b1;
00452       else if(projection>1)
00453         closest=b2;
00454       else
00455         closest = b1+projection*u2;
00456       distance = (x-closest).norm();
00457       
00458       if(min_distance>distance)
00459         min_distance = distance;
00460     }
00461 
00462   return min_distance;
00463 }
00464 
00465 
00466 int Skinned::get_max_weight_influence(int k_vertex,int *k_bone_max,double *weight_max)
00467 {
00468   *weight_max=0.0;
00469   *k_bone_max=-1;
00470   int k_joint=0;
00471   double current_weight=0;
00472   for(k_joint=0;k_joint<skeleton->get_N_joint();k_joint++)
00473     {
00474       current_weight=get_weight(k_vertex,k_joint);
00475       if(current_weight>*weight_max)
00476         {
00477           *weight_max = current_weight;
00478           *k_bone_max = k_joint;
00479         }
00480     }
00481 
00482   return 0;
00483 }
00484 
00485 
00486 int Skinned::automatic_weight_calculation()
00487 {
00488 
00489 
00490 #ifdef DEBUG
00491   printf("\n[Automatic Weight Calculation ...]\n");
00492 #endif 
00493 
00494 
00495 
00496   int N_vertex=mesh->get_vertex_number();
00497   int N_joint = skeleton->get_N_joint();
00498 
00499   weight.resize(0);
00500   index_weight.resize(0);
00501   index_joint.resize(0);
00502   set_size_index_weight(N_vertex);
00503   set_size_index_joint(N_vertex);
00504 
00505 
00506   int k_vertex=0;
00507   int k_joint=0;
00508   for(k_joint=0;k_joint<N_joint;k_joint++)
00509     {
00510       for(k_vertex=0;k_vertex<N_vertex;k_vertex++)
00511         {
00512           add_index_weight(k_vertex,k_vertex+k_joint*N_vertex); 
00513           add_index_joint(k_vertex,k_joint);
00514           add_weight(calculate_weight(k_vertex,k_joint));
00515         }
00516     }
00517 
00518 
00519   //weight normalization
00520   normalize_weight();
00521 
00522   //fill vector of vertex_depending_on_bone
00523   fill_vertex_depending_on_bone();
00524 
00525 
00526 #ifdef DEBUG
00527   printf("[Weight Calculated [OK]]\n\n");
00528 #endif 
00529 
00530   return 0;
00531 }
00532 
00533 double Skinned::calculate_weight(int k_vertex,int k_joint)
00534 {
00535   double dist = 0.0;
00536   double weight_power = WEIGHT_EXPONENT;
00537   dist = get_vertex_to_bone_distance(k_vertex,k_joint);
00538   
00539   double current_weight=0.0;
00540   current_weight = powf(1/dist,weight_power);
00541 
00542   return current_weight;
00543 }
00544 
00545 int Skinned::normalize_weight()
00546 {
00547 
00548   int k_vertex=0;
00549   int k_b=0,k_bone=0;
00550   std::vector <double> vector_weight;
00551   double sum_weight=0.0;
00552   double small_weight = 1.0/200000.0;
00553   for(k_vertex=0;k_vertex<mesh->get_vertex_number();k_vertex++)
00554     {
00555       vector_weight.resize(0);
00556       for(k_b=0;k_b<get_size_index_weight(k_vertex);k_b++)
00557         {
00558           k_bone = get_index_joint(k_vertex,k_b);
00559           vector_weight.push_back(get_weight(k_vertex,k_bone));
00560         }
00561 
00562 
00563       //JUST KEEP THE THREE FIRST MAX WEIGHT (OPTIONAL)
00564       //*********************************************************//
00565       //get three first wax_weights
00566       double max_weight[3]={-10.0,-10.0,-10.0};
00567       int bones_to_keep[3]={-1,-1,-1};
00568       //first pass
00569       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00570         if(vector_weight[k_b]>max_weight[0])
00571           {max_weight[0]=vector_weight[k_b];bones_to_keep[0]=k_b;}
00572       //second pass
00573       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00574         if(k_b!=bones_to_keep[0] && vector_weight[k_b]>max_weight[1])
00575           {max_weight[1]=vector_weight[k_b];bones_to_keep[1]=k_b;}
00576       //third pass
00577       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00578         if(k_b!=bones_to_keep[1] && k_b!=bones_to_keep[0] && vector_weight[k_b]>max_weight[2])
00579           {max_weight[2]=vector_weight[k_b];bones_to_keep[2]=k_b;}
00580       //just keep them
00581       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00582         if(k_b!=bones_to_keep[0] && k_b!=bones_to_keep[1] && k_b!=bones_to_keep[2])
00583           vector_weight[k_b]=0.0;
00584       //**********************************************************//
00585 
00586 
00587       //get sum
00588       sum_weight=0.0;
00589       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00590         sum_weight += vector_weight[k_b];
00591 
00592       //normalize
00593       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00594         vector_weight[k_b] /= sum_weight;
00595 
00596       //get_to_small_weight
00597       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00598         if(vector_weight[k_b]<small_weight)
00599           vector_weight[k_b] = 0.0;
00600 
00601       //get sum again
00602       sum_weight=0.0;
00603       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00604         sum_weight += vector_weight[k_b];
00605 
00606       //normalize again
00607       for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00608         vector_weight[k_b] /= sum_weight;
00609 
00610 
00611       //set weights back
00612       for(k_b=0;k_b<get_size_index_weight(k_vertex);k_b++)
00613         set_weight(k_vertex,k_b,vector_weight[k_b]);
00614     }
00615 
00616   return 0;
00617 }
00618 
00619 
00620 
00621 
00622 

Generated on Mon Mar 30 16:55:54 2009 by  doxygen 1.5.6