Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed. 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00023 #include "GeometryExporter.h" 00024 #include "AnimationExporter.h" 00025 #include "MaterialExporter.h" 00026 00027 template<class Functor> 00028 void forEachObjectInScene(Scene *sce, Functor &f) 00029 { 00030 Base *base= (Base*) sce->base.first; 00031 00032 while(base) { 00033 Object *ob = base->object; 00034 00035 f(ob); 00036 00037 base= base->next; 00038 } 00039 } 00040 00041 void AnimationExporter::exportAnimations(Scene *sce) 00042 { 00043 if(hasAnimations(sce)) { 00044 this->scene = sce; 00045 00046 openLibrary(); 00047 00048 forEachObjectInScene(sce, *this); 00049 00050 closeLibrary(); 00051 } 00052 } 00053 00054 // called for each exported object 00055 void AnimationExporter::operator() (Object *ob) 00056 { 00057 FCurve *fcu; 00058 char * transformName ; 00059 /* bool isMatAnim = false; */ /* UNUSED */ 00060 00061 //Export transform animations 00062 if(ob->adt && ob->adt->action) 00063 { 00064 fcu = (FCurve*)ob->adt->action->curves.first; 00065 00066 //transform matrix export for bones are temporarily disabled here. 00067 if ( ob->type == OB_ARMATURE ) 00068 { 00069 bArmature *arm = (bArmature*)ob->data; 00070 for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) 00071 write_bone_animation_matrix(ob, bone); 00072 } 00073 00074 while (fcu) { 00075 //for armature animations as objects 00076 if ( ob->type == OB_ARMATURE ) 00077 transformName = fcu->rna_path; 00078 else 00079 transformName = extract_transform_name( fcu->rna_path ); 00080 00081 if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) || 00082 (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL)|| 00083 (!strcmp(transformName, "rotation_quaternion"))) 00084 dae_animation(ob ,fcu, transformName, false); 00085 fcu = fcu->next; 00086 } 00087 00088 } 00089 00090 //Export Lamp parameter animations 00091 if( (ob->type == OB_LAMP ) && ((Lamp*)ob ->data)->adt && ((Lamp*)ob ->data)->adt->action ) 00092 { 00093 fcu = (FCurve*)(((Lamp*)ob ->data)->adt->action->curves.first); 00094 while (fcu) { 00095 transformName = extract_transform_name( fcu->rna_path ); 00096 00097 if ((!strcmp(transformName, "color")) || (!strcmp(transformName, "spot_size"))|| (!strcmp(transformName, "spot_blend"))|| 00098 (!strcmp(transformName, "distance")) ) 00099 dae_animation(ob , fcu, transformName, true ); 00100 fcu = fcu->next; 00101 } 00102 } 00103 00104 //Export Camera parameter animations 00105 if( (ob->type == OB_CAMERA ) && ((Camera*)ob ->data)->adt && ((Camera*)ob ->data)->adt->action ) 00106 { 00107 fcu = (FCurve*)(((Camera*)ob ->data)->adt->action->curves.first); 00108 while (fcu) { 00109 transformName = extract_transform_name( fcu->rna_path ); 00110 00111 if ((!strcmp(transformName, "lens"))|| 00112 (!strcmp(transformName, "ortho_scale"))|| 00113 (!strcmp(transformName, "clip_end"))||(!strcmp(transformName, "clip_start"))) 00114 dae_animation(ob , fcu, transformName, true ); 00115 fcu = fcu->next; 00116 } 00117 } 00118 00119 //Export Material parameter animations. 00120 for(int a = 0; a < ob->totcol; a++) 00121 { 00122 Material *ma = give_current_material(ob, a+1); 00123 if (!ma) continue; 00124 if(ma->adt && ma->adt->action) 00125 { 00126 /* isMatAnim = true; */ 00127 fcu = (FCurve*)ma->adt->action->curves.first; 00128 while (fcu) { 00129 transformName = extract_transform_name( fcu->rna_path ); 00130 00131 if ((!strcmp(transformName, "specular_hardness"))||(!strcmp(transformName, "specular_color")) 00132 ||(!strcmp(transformName, "diffuse_color"))||(!strcmp(transformName, "alpha"))|| 00133 (!strcmp(transformName, "ior"))) 00134 dae_animation(ob ,fcu, transformName, true, ma ); 00135 fcu = fcu->next; 00136 } 00137 } 00138 00139 } 00140 } 00141 00142 //euler sources from quternion sources 00143 float * AnimationExporter::get_eul_source_for_quat(Object *ob ) 00144 { 00145 FCurve *fcu = (FCurve*)ob->adt->action->curves.first; 00146 const int keys = fcu->totvert; 00147 float *quat = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values"); 00148 float *eul = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values"); 00149 float temp_quat[4]; 00150 float temp_eul[3]; 00151 while(fcu) 00152 { 00153 char * transformName = extract_transform_name( fcu->rna_path ); 00154 00155 if( !strcmp(transformName, "rotation_quaternion") ) { 00156 for ( int i = 0 ; i < fcu->totvert ; i++){ 00157 *(quat + ( i * 4 ) + fcu->array_index) = fcu->bezt[i].vec[1][1]; 00158 } 00159 } 00160 fcu = fcu->next; 00161 } 00162 00163 for ( int i = 0 ; i < keys ; i++){ 00164 for ( int j = 0;j<4;j++) 00165 temp_quat[j] = quat[(i*4)+j]; 00166 00167 quat_to_eul(temp_eul,temp_quat); 00168 00169 for (int k = 0;k<3;k++) 00170 eul[i*3 + k] = temp_eul[k]; 00171 00172 } 00173 MEM_freeN(quat); 00174 return eul; 00175 00176 } 00177 00178 //Get proper name for bones 00179 std::string AnimationExporter::getObjectBoneName( Object* ob,const FCurve* fcu ) 00180 { 00181 //hard-way to derive the bone name from rna_path. Must find more compact method 00182 std::string rna_path = std::string(fcu->rna_path); 00183 00184 char* boneName = strtok((char *)rna_path.c_str(), "\""); 00185 boneName = strtok(NULL,"\""); 00186 00187 if( boneName != NULL ) 00188 return /*id_name(ob) + "_" +*/ std::string(boneName); 00189 else 00190 return id_name(ob); 00191 } 00192 00193 //convert f-curves to animation curves and write 00194 void AnimationExporter::dae_animation(Object* ob, FCurve *fcu, char* transformName , bool is_param, Material * ma ) 00195 { 00196 const char *axis_name = NULL; 00197 char anim_id[200]; 00198 00199 bool has_tangents = false; 00200 bool quatRotation = false; 00201 00202 if ( !strcmp(transformName, "rotation_quaternion") ) 00203 { 00204 fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n"); 00205 quatRotation = true; 00206 return; 00207 } 00208 00209 //axis names for colors 00210 else if ( !strcmp(transformName, "color")||!strcmp(transformName, "specular_color")||!strcmp(transformName, "diffuse_color")|| 00211 (!strcmp(transformName, "alpha"))) 00212 { 00213 const char *axis_names[] = {"R", "G", "B"}; 00214 if (fcu->array_index < 3) 00215 axis_name = axis_names[fcu->array_index]; 00216 } 00217 00218 //axis names for transforms 00219 else if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) || 00220 (!strcmp(transformName, "rotation_euler"))||(!strcmp(transformName, "rotation_quaternion"))) 00221 { 00222 const char *axis_names[] = {"X", "Y", "Z"}; 00223 if (fcu->array_index < 3) 00224 axis_name = axis_names[fcu->array_index]; 00225 } 00226 00227 //no axis name. single parameter. 00228 else{ 00229 axis_name = ""; 00230 } 00231 00232 std::string ob_name = std::string("null"); 00233 00234 //Create anim Id 00235 if (ob->type == OB_ARMATURE) 00236 { 00237 ob_name = getObjectBoneName( ob , fcu); 00238 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char*)translate_id(ob_name).c_str(), 00239 transformName, axis_name); 00240 } 00241 else 00242 { 00243 if (ma) 00244 ob_name = id_name(ob) + "_material"; 00245 else 00246 ob_name = id_name(ob); 00247 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(), 00248 fcu->rna_path, axis_name); 00249 } 00250 00251 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); 00252 00253 // create input source 00254 std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name); 00255 00256 // create output source 00257 std::string output_id ; 00258 00259 //quat rotations are skipped for now, because of complications with determining axis. 00260 if(quatRotation) 00261 { 00262 float * eul = get_eul_source_for_quat(ob); 00263 float * eul_axis = (float*)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values"); 00264 for ( int i = 0 ; i< fcu->totvert ; i++) 00265 eul_axis[i] = eul[i*3 + fcu->array_index]; 00266 output_id= create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis , fcu->totvert, quatRotation, anim_id, axis_name); 00267 MEM_freeN(eul); 00268 MEM_freeN(eul_axis); 00269 } 00270 else 00271 { 00272 output_id= create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name); 00273 } 00274 // create interpolations source 00275 std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents); 00276 00277 // handle tangents (if required) 00278 std::string intangent_id; 00279 std::string outtangent_id; 00280 00281 if (has_tangents) { 00282 // create in_tangent source 00283 intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name); 00284 00285 // create out_tangent source 00286 outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name); 00287 } 00288 00289 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; 00290 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); 00291 std::string empty; 00292 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); 00293 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); 00294 00295 // this input is required 00296 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); 00297 00298 if (has_tangents) { 00299 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id)); 00300 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id)); 00301 } 00302 00303 addSampler(sampler); 00304 00305 std::string target ; 00306 00307 if ( !is_param ) 00308 target = translate_id(ob_name) 00309 + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true); 00310 else 00311 { 00312 if ( ob->type == OB_LAMP ) 00313 target = get_light_id(ob) 00314 + "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true); 00315 00316 if ( ob->type == OB_CAMERA ) 00317 target = get_camera_id(ob) 00318 + "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true); 00319 00320 if( ma ) 00321 target = translate_id(id_name(ma)) + "-effect" 00322 +"/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true); 00323 } 00324 addChannel(COLLADABU::URI(empty, sampler_id), target); 00325 00326 closeAnimation(); 00327 } 00328 00329 00330 00331 //write bone animations in transform matrix sources 00332 void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone) 00333 { 00334 if (!ob_arm->adt) 00335 return; 00336 00337 //This will only export animations of bones in deform group. 00338 /*if(!is_bone_deform_group(bone)) 00339 return;*/ 00340 00341 sample_and_write_bone_animation_matrix(ob_arm, bone); 00342 00343 for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) 00344 write_bone_animation_matrix(ob_arm, child); 00345 } 00346 00347 bool AnimationExporter::is_bone_deform_group(Bone * bone) 00348 { 00349 bool is_def; 00350 //Check if current bone is deform 00351 if((bone->flag & BONE_NO_DEFORM) == 0 ) return true; 00352 //Check child bones 00353 else 00354 { 00355 for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next){ 00356 //loop through all the children until deform bone is found, and then return 00357 is_def = is_bone_deform_group(child); 00358 if (is_def) return true; 00359 } 00360 } 00361 //no deform bone found in children also 00362 return false; 00363 } 00364 00365 void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone) 00366 { 00367 bArmature *arm = (bArmature*)ob_arm->data; 00368 int flag = arm->flag; 00369 std::vector<float> fra; 00370 //char prefix[256]; 00371 00372 FCurve* fcu = (FCurve*)ob_arm->adt->action->curves.first; 00373 while(fcu) 00374 { 00375 std::string bone_name = getObjectBoneName(ob_arm,fcu); 00376 int val = BLI_strcasecmp((char*)bone_name.c_str(),bone->name); 00377 if(val==0) break; 00378 fcu = fcu->next; 00379 } 00380 00381 if(!(fcu)) return; 00382 bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); 00383 if (!pchan) 00384 return; 00385 00386 find_frames(ob_arm, fra); 00387 00388 if (flag & ARM_RESTPOS) { 00389 arm->flag &= ~ARM_RESTPOS; 00390 where_is_pose(scene, ob_arm); 00391 } 00392 00393 if (fra.size()) { 00394 dae_baked_animation(fra ,ob_arm, bone ); 00395 } 00396 00397 if (flag & ARM_RESTPOS) 00398 arm->flag = flag; 00399 where_is_pose(scene, ob_arm); 00400 } 00401 00402 void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm , Bone *bone) 00403 { 00404 std::string ob_name = id_name(ob_arm); 00405 std::string bone_name = bone->name; 00406 char anim_id[200]; 00407 00408 if (!fra.size()) 00409 return; 00410 00411 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(), 00412 (char*)translate_id(bone_name).c_str(), "pose_matrix"); 00413 00414 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); 00415 00416 // create input source 00417 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, ""); 00418 00419 // create output source 00420 std::string output_id; 00421 output_id = create_4x4_source( fra, ob_arm , bone , anim_id); 00422 00423 // create interpolations source 00424 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, ""); 00425 00426 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; 00427 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); 00428 std::string empty; 00429 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); 00430 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); 00431 00432 // TODO create in/out tangents source 00433 00434 // this input is required 00435 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); 00436 00437 addSampler(sampler); 00438 00439 std::string target = translate_id(bone_name) + "/transform"; 00440 addChannel(COLLADABU::URI(empty, sampler_id), target); 00441 00442 closeAnimation(); 00443 } 00444 00445 // dae_bone_animation -> add_bone_animation 00446 // (blend this into dae_bone_animation) 00447 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name) 00448 { 00449 const char *axis_names[] = {"X", "Y", "Z"}; 00450 const char *axis_name = NULL; 00451 char anim_id[200]; 00452 bool is_rot = tm_type == 0; 00453 00454 if (!fra.size()) 00455 return; 00456 00457 char rna_path[200]; 00458 BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(), 00459 tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location")); 00460 00461 if (axis > -1) 00462 axis_name = axis_names[axis]; 00463 00464 std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false); 00465 00466 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(), 00467 (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str()); 00468 00469 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); 00470 00471 // create input source 00472 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name); 00473 00474 // create output source 00475 std::string output_id; 00476 if (axis == -1) 00477 output_id = create_xyz_source(values, fra.size(), anim_id); 00478 else 00479 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name); 00480 00481 // create interpolations source 00482 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name); 00483 00484 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; 00485 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); 00486 std::string empty; 00487 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); 00488 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); 00489 00490 // TODO create in/out tangents source 00491 00492 // this input is required 00493 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); 00494 00495 addSampler(sampler); 00496 00497 std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid; 00498 addChannel(COLLADABU::URI(empty, sampler_id), target); 00499 00500 closeAnimation(); 00501 } 00502 00503 float AnimationExporter::convert_time(float frame) 00504 { 00505 return FRA2TIME(frame); 00506 } 00507 00508 float AnimationExporter::convert_angle(float angle) 00509 { 00510 return COLLADABU::Math::Utils::radToDegF(angle); 00511 } 00512 00513 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic) 00514 { 00515 switch(semantic) { 00516 case COLLADASW::InputSemantic::INPUT: 00517 return INPUT_SOURCE_ID_SUFFIX; 00518 case COLLADASW::InputSemantic::OUTPUT: 00519 return OUTPUT_SOURCE_ID_SUFFIX; 00520 case COLLADASW::InputSemantic::INTERPOLATION: 00521 return INTERPOLATION_SOURCE_ID_SUFFIX; 00522 case COLLADASW::InputSemantic::IN_TANGENT: 00523 return INTANGENT_SOURCE_ID_SUFFIX; 00524 case COLLADASW::InputSemantic::OUT_TANGENT: 00525 return OUTTANGENT_SOURCE_ID_SUFFIX; 00526 default: 00527 break; 00528 } 00529 return ""; 00530 } 00531 00532 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, 00533 COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform) 00534 { 00535 switch(semantic) { 00536 case COLLADASW::InputSemantic::INPUT: 00537 param.push_back("TIME"); 00538 break; 00539 case COLLADASW::InputSemantic::OUTPUT: 00540 if (is_rot) { 00541 param.push_back("ANGLE"); 00542 } 00543 else { 00544 if (axis) { 00545 param.push_back(axis); 00546 } 00547 else 00548 if ( transform ) 00549 { 00550 param.push_back("TRANSFORM"); 00551 }else{ //assumes if axis isn't specified all axises are added 00552 param.push_back("X"); 00553 param.push_back("Y"); 00554 param.push_back("Z"); 00555 } 00556 } 00557 break; 00558 case COLLADASW::InputSemantic::IN_TANGENT: 00559 case COLLADASW::InputSemantic::OUT_TANGENT: 00560 param.push_back("X"); 00561 param.push_back("Y"); 00562 break; 00563 default: 00564 break; 00565 } 00566 } 00567 00568 void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length) 00569 { 00570 switch (semantic) { 00571 case COLLADASW::InputSemantic::INPUT: 00572 *length = 1; 00573 values[0] = convert_time(bezt->vec[1][0]); 00574 break; 00575 case COLLADASW::InputSemantic::OUTPUT: 00576 *length = 1; 00577 if (rotation) { 00578 values[0] = RAD2DEGF(bezt->vec[1][1]); 00579 } 00580 else { 00581 values[0] = bezt->vec[1][1]; 00582 } 00583 break; 00584 00585 case COLLADASW::InputSemantic::IN_TANGENT: 00586 *length = 2; 00587 values[0] = convert_time(bezt->vec[0][0]); 00588 if (bezt->ipo != BEZT_IPO_BEZ) { 00589 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data 00590 values[0] = 0; 00591 values[1] = 0; 00592 } 00593 else if (rotation) { 00594 values[1] = RAD2DEGF(bezt->vec[0][1]); 00595 } else { 00596 values[1] = bezt->vec[0][1]; 00597 } 00598 break; 00599 00600 case COLLADASW::InputSemantic::OUT_TANGENT: 00601 *length = 2; 00602 values[0] = convert_time(bezt->vec[2][0]); 00603 if (bezt->ipo != BEZT_IPO_BEZ) { 00604 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data 00605 values[0] = 0; 00606 values[1] = 0; 00607 } 00608 else if (rotation) { 00609 values[1] = RAD2DEGF(bezt->vec[2][1]); 00610 } else { 00611 values[1] = bezt->vec[2][1]; 00612 } 00613 break; 00614 break; 00615 default: 00616 *length = 0; 00617 break; 00618 } 00619 } 00620 00621 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name) 00622 { 00623 std::string source_id = anim_id + get_semantic_suffix(semantic); 00624 00625 //bool is_rotation = !strcmp(fcu->rna_path, "rotation"); 00626 bool is_angle = false; 00627 00628 if (strstr(fcu->rna_path, "rotation")) is_angle = true; 00629 00630 COLLADASW::FloatSourceF source(mSW); 00631 source.setId(source_id); 00632 source.setArrayId(source_id + ARRAY_ID_SUFFIX); 00633 source.setAccessorCount(fcu->totvert); 00634 00635 switch (semantic) { 00636 case COLLADASW::InputSemantic::INPUT: 00637 case COLLADASW::InputSemantic::OUTPUT: 00638 source.setAccessorStride(1); 00639 break; 00640 case COLLADASW::InputSemantic::IN_TANGENT: 00641 case COLLADASW::InputSemantic::OUT_TANGENT: 00642 source.setAccessorStride(2); 00643 break; 00644 default: 00645 break; 00646 } 00647 00648 00649 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); 00650 add_source_parameters(param, semantic, is_angle, axis_name, false); 00651 00652 source.prepareToAppendValues(); 00653 00654 for (unsigned int i = 0; i < fcu->totvert; i++) { 00655 float values[3]; // be careful! 00656 int length = 0; 00657 get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length); 00658 for (int j = 0; j < length; j++) 00659 source.appendValues(values[j]); 00660 } 00661 00662 source.finish(); 00663 00664 return source_id; 00665 } 00666 00667 //Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified ) 00668 std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name) 00669 { 00670 std::string source_id = anim_id + get_semantic_suffix(semantic); 00671 00672 COLLADASW::FloatSourceF source(mSW); 00673 source.setId(source_id); 00674 source.setArrayId(source_id + ARRAY_ID_SUFFIX); 00675 source.setAccessorCount(tot); 00676 source.setAccessorStride(1); 00677 00678 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); 00679 add_source_parameters(param, semantic, is_rot, axis_name, false); 00680 00681 source.prepareToAppendValues(); 00682 00683 for (int i = 0; i < tot; i++) { 00684 float val = v[i]; 00686 // val = convert_time(val); 00687 //else 00688 if (is_rot) 00689 val = RAD2DEGF(val); 00690 source.appendValues(val); 00691 } 00692 00693 source.finish(); 00694 00695 return source_id; 00696 } 00697 // only used for sources with INPUT semantic 00698 std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name) 00699 { 00700 std::string source_id = anim_id + get_semantic_suffix(semantic); 00701 00702 COLLADASW::FloatSourceF source(mSW); 00703 source.setId(source_id); 00704 source.setArrayId(source_id + ARRAY_ID_SUFFIX); 00705 source.setAccessorCount(fra.size()); 00706 source.setAccessorStride(1); 00707 00708 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); 00709 add_source_parameters(param, semantic, is_rot, axis_name, false); 00710 00711 source.prepareToAppendValues(); 00712 00713 std::vector<float>::iterator it; 00714 for (it = fra.begin(); it != fra.end(); it++) { 00715 float val = *it; 00716 //if (semantic == COLLADASW::InputSemantic::INPUT) 00717 val = convert_time(val); 00718 /*else if (is_rot) 00719 val = convert_angle(val);*/ 00720 source.appendValues(val); 00721 } 00722 00723 source.finish(); 00724 00725 return source_id; 00726 } 00727 00728 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames , Object * ob_arm, Bone *bone , const std::string& anim_id) 00729 { 00730 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; 00731 std::string source_id = anim_id + get_semantic_suffix(semantic); 00732 00733 COLLADASW::Float4x4Source source(mSW); 00734 source.setId(source_id); 00735 source.setArrayId(source_id + ARRAY_ID_SUFFIX); 00736 source.setAccessorCount(frames.size()); 00737 source.setAccessorStride(16); 00738 00739 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); 00740 add_source_parameters(param, semantic, false, NULL, true); 00741 00742 source.prepareToAppendValues(); 00743 00744 bPoseChannel *parchan = NULL; 00745 bPoseChannel *pchan = NULL; 00746 bPose *pose = ob_arm->pose; 00747 00748 pchan = get_pose_channel(pose, bone->name); 00749 00750 if (!pchan) 00751 return ""; 00752 00753 parchan = pchan->parent; 00754 00755 enable_fcurves(ob_arm->adt->action, bone->name); 00756 00757 std::vector<float>::iterator it; 00758 int j = 0; 00759 for (it = frames.begin(); it != frames.end(); it++) { 00760 float mat[4][4], ipar[4][4]; 00761 00762 float ctime = BKE_frame_to_ctime(scene, *it); 00763 00764 BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM); 00765 where_is_pose_bone(scene, ob_arm, pchan, ctime, 1); 00766 00767 // compute bone local mat 00768 if (bone->parent) { 00769 invert_m4_m4(ipar, parchan->pose_mat); 00770 mult_m4_m4m4(mat, ipar, pchan->pose_mat); 00771 } 00772 else 00773 copy_m4_m4(mat, pchan->pose_mat); 00774 UnitConverter converter; 00775 00776 float outmat[4][4]; 00777 converter.mat4_to_dae(outmat,mat); 00778 00779 00780 source.appendValues(outmat); 00781 00782 00783 j++; 00784 } 00785 00786 enable_fcurves(ob_arm->adt->action, NULL); 00787 00788 source.finish(); 00789 00790 return source_id; 00791 } 00792 // only used for sources with OUTPUT semantic ( locations and scale) 00793 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id) 00794 { 00795 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; 00796 std::string source_id = anim_id + get_semantic_suffix(semantic); 00797 00798 COLLADASW::FloatSourceF source(mSW); 00799 source.setId(source_id); 00800 source.setArrayId(source_id + ARRAY_ID_SUFFIX); 00801 source.setAccessorCount(tot); 00802 source.setAccessorStride(3); 00803 00804 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); 00805 add_source_parameters(param, semantic, false, NULL, false); 00806 00807 source.prepareToAppendValues(); 00808 00809 for (int i = 0; i < tot; i++) { 00810 source.appendValues(*v, *(v + 1), *(v + 2)); 00811 v += 3; 00812 } 00813 00814 source.finish(); 00815 00816 return source_id; 00817 } 00818 00819 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents) 00820 { 00821 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); 00822 00823 COLLADASW::NameSource source(mSW); 00824 source.setId(source_id); 00825 source.setArrayId(source_id + ARRAY_ID_SUFFIX); 00826 source.setAccessorCount(fcu->totvert); 00827 source.setAccessorStride(1); 00828 00829 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); 00830 param.push_back("INTERPOLATION"); 00831 00832 source.prepareToAppendValues(); 00833 00834 *has_tangents = false; 00835 00836 for (unsigned int i = 0; i < fcu->totvert; i++) { 00837 if (fcu->bezt[i].ipo==BEZT_IPO_BEZ) { 00838 source.appendValues(BEZIER_NAME); 00839 *has_tangents = true; 00840 } else if (fcu->bezt[i].ipo==BEZT_IPO_CONST) { 00841 source.appendValues(STEP_NAME); 00842 } else { // BEZT_IPO_LIN 00843 source.appendValues(LINEAR_NAME); 00844 } 00845 } 00846 // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS 00847 00848 source.finish(); 00849 00850 return source_id; 00851 } 00852 00853 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name) 00854 { 00855 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); 00856 00857 COLLADASW::NameSource source(mSW); 00858 source.setId(source_id); 00859 source.setArrayId(source_id + ARRAY_ID_SUFFIX); 00860 source.setAccessorCount(tot); 00861 source.setAccessorStride(1); 00862 00863 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); 00864 param.push_back("INTERPOLATION"); 00865 00866 source.prepareToAppendValues(); 00867 00868 for (int i = 0; i < tot; i++) { 00869 source.appendValues(LINEAR_NAME); 00870 } 00871 00872 source.finish(); 00873 00874 return source_id; 00875 } 00876 00877 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis) 00878 { 00879 std::string tm_name; 00880 // when given rna_path, determine tm_type from it 00881 if (rna_path) { 00882 char *name = extract_transform_name(rna_path); 00883 00884 if (!strcmp(name, "color")) 00885 tm_type = 1; 00886 else if (!strcmp(name, "spot_size")) 00887 tm_type = 2; 00888 else if (!strcmp(name, "spot_blend")) 00889 tm_type = 3; 00890 else if (!strcmp(name, "distance")) 00891 tm_type = 4; 00892 else 00893 tm_type = -1; 00894 } 00895 00896 switch (tm_type) { 00897 case 1: 00898 tm_name = "color"; 00899 break; 00900 case 2: 00901 tm_name = "fall_off_angle"; 00902 break; 00903 case 3: 00904 tm_name = "fall_off_exponent"; 00905 break; 00906 case 4: 00907 tm_name = "blender/blender_dist"; 00908 break; 00909 00910 default: 00911 tm_name = ""; 00912 break; 00913 } 00914 00915 if (tm_name.size()) { 00916 if (axis_name[0]) 00917 return tm_name + "." + std::string(axis_name); 00918 else 00919 return tm_name; 00920 } 00921 00922 return std::string(""); 00923 } 00924 00925 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis) 00926 { 00927 std::string tm_name; 00928 // when given rna_path, determine tm_type from it 00929 if (rna_path) { 00930 char *name = extract_transform_name(rna_path); 00931 00932 if (!strcmp(name, "lens")) 00933 tm_type = 0; 00934 else if (!strcmp(name, "ortho_scale")) 00935 tm_type = 1; 00936 else if (!strcmp(name, "clip_end")) 00937 tm_type = 2; 00938 else if (!strcmp(name, "clip_start")) 00939 tm_type = 3; 00940 00941 else 00942 tm_type = -1; 00943 } 00944 00945 switch (tm_type) { 00946 case 0: 00947 tm_name = "xfov"; 00948 break; 00949 case 1: 00950 tm_name = "xmag"; 00951 break; 00952 case 2: 00953 tm_name = "zfar"; 00954 break; 00955 case 3: 00956 tm_name = "znear"; 00957 break; 00958 00959 default: 00960 tm_name = ""; 00961 break; 00962 } 00963 00964 if (tm_name.size()) { 00965 if (axis_name[0]) 00966 return tm_name + "." + std::string(axis_name); 00967 else 00968 return tm_name; 00969 } 00970 00971 return std::string(""); 00972 } 00973 00974 // Assign sid of the animated parameter or transform 00975 // for rotation, axis name is always appended and the value of append_axis is ignored 00976 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis) 00977 { 00978 std::string tm_name; 00979 bool is_rotation =false; 00980 // when given rna_path, determine tm_type from it 00981 if (rna_path) { 00982 char *name = extract_transform_name(rna_path); 00983 00984 if (!strcmp(name, "rotation_euler")) 00985 tm_type = 0; 00986 else if (!strcmp(name, "rotation_quaternion")) 00987 tm_type = 1; 00988 else if (!strcmp(name, "scale")) 00989 tm_type = 2; 00990 else if (!strcmp(name, "location")) 00991 tm_type = 3; 00992 else if (!strcmp(name, "specular_hardness")) 00993 tm_type = 4; 00994 else if (!strcmp(name, "specular_color")) 00995 tm_type = 5; 00996 else if (!strcmp(name, "diffuse_color")) 00997 tm_type = 6; 00998 else if (!strcmp(name, "alpha")) 00999 tm_type = 7; 01000 else if (!strcmp(name, "ior")) 01001 tm_type = 8; 01002 01003 else 01004 tm_type = -1; 01005 } 01006 01007 switch (tm_type) { 01008 case 0: 01009 case 1: 01010 tm_name = "rotation"; 01011 is_rotation = true; 01012 break; 01013 case 2: 01014 tm_name = "scale"; 01015 break; 01016 case 3: 01017 tm_name = "location"; 01018 break; 01019 case 4: 01020 tm_name = "shininess"; 01021 break; 01022 case 5: 01023 tm_name = "specular"; 01024 break; 01025 case 6: 01026 tm_name = "diffuse"; 01027 break; 01028 case 7: 01029 tm_name = "transparency"; 01030 break; 01031 case 8: 01032 tm_name = "index_of_refraction"; 01033 break; 01034 01035 default: 01036 tm_name = ""; 01037 break; 01038 } 01039 01040 if (tm_name.size()) { 01041 if (is_rotation) 01042 return tm_name + std::string(axis_name) + ".ANGLE"; 01043 else 01044 if (axis_name[0]) 01045 return tm_name + "." + std::string(axis_name); 01046 else 01047 return tm_name; 01048 } 01049 01050 return std::string(""); 01051 } 01052 01053 char* AnimationExporter::extract_transform_name(char *rna_path) 01054 { 01055 char *dot = strrchr(rna_path, '.'); 01056 return dot ? (dot + 1) : rna_path; 01057 } 01058 01059 //find keyframes of all the objects animations 01060 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra) 01061 { 01062 FCurve *fcu= (FCurve*)ob->adt->action->curves.first; 01063 01064 for (; fcu; fcu = fcu->next) { 01065 01066 for (unsigned int i = 0; i < fcu->totvert; i++) { 01067 float f = fcu->bezt[i].vec[1][0]; 01068 if (std::find(fra.begin(), fra.end(), f) == fra.end()) 01069 fra.push_back(f); 01070 } 01071 } 01072 01073 // keep the keys in ascending order 01074 std::sort(fra.begin(), fra.end()); 01075 } 01076 01077 01078 01079 // enable fcurves driving a specific bone, disable all the rest 01080 // if bone_name = NULL enable all fcurves 01081 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name) 01082 { 01083 FCurve *fcu; 01084 char prefix[200]; 01085 01086 if (bone_name) 01087 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name); 01088 01089 for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) { 01090 if (bone_name) { 01091 if (!strncmp(fcu->rna_path, prefix, strlen(prefix))) 01092 fcu->flag &= ~FCURVE_DISABLED; 01093 else 01094 fcu->flag |= FCURVE_DISABLED; 01095 } 01096 else { 01097 fcu->flag &= ~FCURVE_DISABLED; 01098 } 01099 } 01100 } 01101 01102 bool AnimationExporter::hasAnimations(Scene *sce) 01103 { 01104 Base *base= (Base*) sce->base.first; 01105 01106 while(base) { 01107 Object *ob = base->object; 01108 01109 FCurve *fcu = 0; 01110 //Check for object transform animations 01111 if(ob->adt && ob->adt->action) 01112 fcu = (FCurve*)ob->adt->action->curves.first; 01113 //Check for Lamp parameter animations 01114 else if( (ob->type == OB_LAMP ) && ((Lamp*)ob ->data)->adt && ((Lamp*)ob ->data)->adt->action ) 01115 fcu = (FCurve*)(((Lamp*)ob ->data)->adt->action->curves.first); 01116 //Check for Camera parameter animations 01117 else if( (ob->type == OB_CAMERA ) && ((Camera*)ob ->data)->adt && ((Camera*)ob ->data)->adt->action ) 01118 fcu = (FCurve*)(((Camera*)ob ->data)->adt->action->curves.first); 01119 01120 //Check Material Effect parameter animations. 01121 for(int a = 0; a < ob->totcol; a++) 01122 { 01123 Material *ma = give_current_material(ob, a+1); 01124 if (!ma) continue; 01125 if(ma->adt && ma->adt->action) 01126 { 01127 fcu = (FCurve*)ma->adt->action->curves.first; 01128 } 01129 } 01130 01131 if ( fcu) 01132 return true; 01133 base= base->next; 01134 } 01135 return false; 01136 } 01137 01138 //------------------------------- Not used in the new system.-------------------------------------------------------- 01139 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode) 01140 { 01141 if (rotmode > 0) 01142 find_frames(ob, fra, prefix, "rotation_euler"); 01143 else if (rotmode == ROT_MODE_QUAT) 01144 find_frames(ob, fra, prefix, "rotation_quaternion"); 01145 /*else if (rotmode == ROT_MODE_AXISANGLE) 01146 ;*/ 01147 } 01148 01149 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name) 01150 { 01151 FCurve *fcu= (FCurve*)ob->adt->action->curves.first; 01152 01153 for (; fcu; fcu = fcu->next) { 01154 if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix))) 01155 continue; 01156 01157 char *name = extract_transform_name(fcu->rna_path); 01158 if (!strcmp(name, tm_name)) { 01159 for (unsigned int i = 0; i < fcu->totvert; i++) { 01160 float f = fcu->bezt[i].vec[1][0]; 01161 if (std::find(fra.begin(), fra.end(), f) == fra.end()) 01162 fra.push_back(f); 01163 } 01164 } 01165 } 01166 01167 // keep the keys in ascending order 01168 std::sort(fra.begin(), fra.end()); 01169 } 01170 01171 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone) 01172 { 01173 if (!ob_arm->adt) 01174 return; 01175 01176 //write bone animations for 3 transform types 01177 //i=0 --> rotations 01178 //i=1 --> scale 01179 //i=2 --> location 01180 for (int i = 0; i < 3; i++) 01181 sample_and_write_bone_animation(ob_arm, bone, i); 01182 01183 for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) 01184 write_bone_animation(ob_arm, child); 01185 } 01186 01187 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type) 01188 { 01189 bArmature *arm = (bArmature*)ob_arm->data; 01190 int flag = arm->flag; 01191 std::vector<float> fra; 01192 char prefix[256]; 01193 01194 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name); 01195 01196 bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); 01197 if (!pchan) 01198 return; 01199 //Fill frame array with key frame values framed at @param:transform_type 01200 switch (transform_type) { 01201 case 0: 01202 find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode); 01203 break; 01204 case 1: 01205 find_frames(ob_arm, fra, prefix, "scale"); 01206 break; 01207 case 2: 01208 find_frames(ob_arm, fra, prefix, "location"); 01209 break; 01210 default: 01211 return; 01212 } 01213 01214 // exit rest position 01215 if (flag & ARM_RESTPOS) { 01216 arm->flag &= ~ARM_RESTPOS; 01217 where_is_pose(scene, ob_arm); 01218 } 01219 //v array will hold all values which will be exported. 01220 if (fra.size()) { 01221 float *values = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames"); 01222 sample_animation(values, fra, transform_type, bone, ob_arm, pchan); 01223 01224 if (transform_type == 0) { 01225 // write x, y, z curves separately if it is rotation 01226 float *axisValues = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames"); 01227 01228 for (int i = 0; i < 3; i++) { 01229 for (unsigned int j = 0; j < fra.size(); j++) 01230 axisValues[j] = values[j * 3 + i]; 01231 01232 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name); 01233 } 01234 MEM_freeN(axisValues); 01235 } 01236 else { 01237 // write xyz at once if it is location or scale 01238 dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name); 01239 } 01240 01241 MEM_freeN(values); 01242 } 01243 01244 // restore restpos 01245 if (flag & ARM_RESTPOS) 01246 arm->flag = flag; 01247 where_is_pose(scene, ob_arm); 01248 } 01249 01250 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan) 01251 { 01252 bPoseChannel *parchan = NULL; 01253 bPose *pose = ob_arm->pose; 01254 01255 pchan = get_pose_channel(pose, bone->name); 01256 01257 if (!pchan) 01258 return; 01259 01260 parchan = pchan->parent; 01261 01262 enable_fcurves(ob_arm->adt->action, bone->name); 01263 01264 std::vector<float>::iterator it; 01265 for (it = frames.begin(); it != frames.end(); it++) { 01266 float mat[4][4], ipar[4][4]; 01267 01268 float ctime = BKE_frame_to_ctime(scene, *it); 01269 01270 01271 BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM); 01272 where_is_pose_bone(scene, ob_arm, pchan, ctime, 1); 01273 01274 // compute bone local mat 01275 if (bone->parent) { 01276 invert_m4_m4(ipar, parchan->pose_mat); 01277 mult_m4_m4m4(mat, ipar, pchan->pose_mat); 01278 } 01279 else 01280 copy_m4_m4(mat, pchan->pose_mat); 01281 01282 switch (type) { 01283 case 0: 01284 mat4_to_eul(v, mat); 01285 break; 01286 case 1: 01287 mat4_to_size(v, mat); 01288 break; 01289 case 2: 01290 copy_v3_v3(v, mat[3]); 01291 break; 01292 } 01293 01294 v += 3; 01295 } 01296 01297 enable_fcurves(ob_arm->adt->action, NULL); 01298 }