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
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
00520 normalize_weight();
00521
00522
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
00564
00565
00566 double max_weight[3]={-10.0,-10.0,-10.0};
00567 int bones_to_keep[3]={-1,-1,-1};
00568
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
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
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
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
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
00593 for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00594 vector_weight[k_b] /= sum_weight;
00595
00596
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
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
00607 for(k_b=0;k_b<(int)vector_weight.size();k_b++)
00608 vector_weight[k_b] /= sum_weight;
00609
00610
00611
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