diff options
Diffstat (limited to 'source/blender/collada')
65 files changed, 11514 insertions, 11328 deletions
diff --git a/source/blender/collada/AnimationClipExporter.cpp b/source/blender/collada/AnimationClipExporter.cpp index 4a4ad6f7fab..5868c24e6cd 100644 --- a/source/blender/collada/AnimationClipExporter.cpp +++ b/source/blender/collada/AnimationClipExporter.cpp @@ -20,30 +20,31 @@ void AnimationClipExporter::exportAnimationClips(Scene *sce) { - openLibrary(); - std::map<std::string, COLLADASW::ColladaAnimationClip *> clips; + openLibrary(); + std::map<std::string, COLLADASW::ColladaAnimationClip *> clips; - std::vector<std::vector<std::string>>::iterator anim_meta_entry; - for (anim_meta_entry = anim_meta.begin(); anim_meta_entry != anim_meta.end(); ++anim_meta_entry) { - std::vector<std::string> entry = *anim_meta_entry; - std::string action_id = entry[0]; - std::string action_name = entry[1]; + std::vector<std::vector<std::string>>::iterator anim_meta_entry; + for (anim_meta_entry = anim_meta.begin(); anim_meta_entry != anim_meta.end(); + ++anim_meta_entry) { + std::vector<std::string> entry = *anim_meta_entry; + std::string action_id = entry[0]; + std::string action_name = entry[1]; - std::map<std::string, COLLADASW::ColladaAnimationClip *>::iterator it = clips.find(action_name); - if (it == clips.end()) - { - COLLADASW::ColladaAnimationClip *clip = new COLLADASW::ColladaAnimationClip(action_name); - clips[action_name] = clip; - } - COLLADASW::ColladaAnimationClip *clip = clips[action_name]; - clip->setInstancedAnimation(action_id); - } + std::map<std::string, COLLADASW::ColladaAnimationClip *>::iterator it = clips.find( + action_name); + if (it == clips.end()) { + COLLADASW::ColladaAnimationClip *clip = new COLLADASW::ColladaAnimationClip(action_name); + clips[action_name] = clip; + } + COLLADASW::ColladaAnimationClip *clip = clips[action_name]; + clip->setInstancedAnimation(action_id); + } - std::map<std::string, COLLADASW::ColladaAnimationClip *>::iterator clips_it; - for (clips_it = clips.begin(); clips_it != clips.end(); clips_it++) { - COLLADASW::ColladaAnimationClip *clip = (COLLADASW::ColladaAnimationClip *)clips_it->second; - addAnimationClip(*clip); - } + std::map<std::string, COLLADASW::ColladaAnimationClip *>::iterator clips_it; + for (clips_it = clips.begin(); clips_it != clips.end(); clips_it++) { + COLLADASW::ColladaAnimationClip *clip = (COLLADASW::ColladaAnimationClip *)clips_it->second; + addAnimationClip(*clip); + } - closeLibrary(); + closeLibrary(); } diff --git a/source/blender/collada/AnimationClipExporter.h b/source/blender/collada/AnimationClipExporter.h index fd19e8eda5a..6d67ab7c406 100644 --- a/source/blender/collada/AnimationClipExporter.h +++ b/source/blender/collada/AnimationClipExporter.h @@ -20,25 +20,27 @@ #include "COLLADASWLibraryAnimationClips.h" +class AnimationClipExporter : COLLADASW::LibraryAnimationClips { + private: + Depsgraph *depsgraph; + Scene *scene; + COLLADASW::StreamWriter *sw; + const ExportSettings *export_settings; + std::vector<std::vector<std::string>> anim_meta; -class AnimationClipExporter:COLLADASW::LibraryAnimationClips { -private: - Depsgraph *depsgraph; - Scene *scene; - COLLADASW::StreamWriter *sw; - const ExportSettings *export_settings; - std::vector<std::vector<std::string>> anim_meta; + public: + AnimationClipExporter(Depsgraph *depsgraph, + COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings, + std::vector<std::vector<std::string>> anim_meta) + : COLLADASW::LibraryAnimationClips(sw), + depsgraph(depsgraph), + scene(nullptr), + sw(sw), + export_settings(export_settings), + anim_meta(anim_meta) + { + } -public: - - AnimationClipExporter(Depsgraph *depsgraph , COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, std::vector<std::vector<std::string>> anim_meta) : - COLLADASW::LibraryAnimationClips(sw), - depsgraph(depsgraph), - scene(nullptr), - sw(sw), - export_settings(export_settings), - anim_meta(anim_meta) - {} - - void exportAnimationClips(Scene *sce); + void exportAnimationClips(Scene *sce); }; diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index e9babea7b3d..bfef2d76a3d 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -29,140 +29,138 @@ std::string EMPTY_STRING; std::string AnimationExporter::get_axis_name(std::string channel, int id) { - static std::map<std::string, std::vector<std::string>> BC_COLLADA_AXIS_FROM_TYPE = { - { "color" ,{ "R", "G", "B" } }, - { "specular_color",{ "R", "G", "B" } }, - { "diffuse_color",{ "R", "G", "B" } }, - { "alpha",{ "R", "G", "B" } }, - { "scale",{ "X", "Y", "Z" } }, - { "location",{ "X", "Y", "Z" } }, - { "rotation_euler",{ "X", "Y", "Z" } } - }; - - std::map<std::string, std::vector<std::string>>::const_iterator it; - it = BC_COLLADA_AXIS_FROM_TYPE.find(channel); - if (it == BC_COLLADA_AXIS_FROM_TYPE.end()) - return ""; - - const std::vector<std::string> &subchannel = it->second; - if (id >= subchannel.size()) - return ""; - return subchannel[id]; + static std::map<std::string, std::vector<std::string>> BC_COLLADA_AXIS_FROM_TYPE = { + {"color", {"R", "G", "B"}}, + {"specular_color", {"R", "G", "B"}}, + {"diffuse_color", {"R", "G", "B"}}, + {"alpha", {"R", "G", "B"}}, + {"scale", {"X", "Y", "Z"}}, + {"location", {"X", "Y", "Z"}}, + {"rotation_euler", {"X", "Y", "Z"}}}; + + std::map<std::string, std::vector<std::string>>::const_iterator it; + it = BC_COLLADA_AXIS_FROM_TYPE.find(channel); + if (it == BC_COLLADA_AXIS_FROM_TYPE.end()) + return ""; + + const std::vector<std::string> &subchannel = it->second; + if (id >= subchannel.size()) + return ""; + return subchannel[id]; } bool AnimationExporter::open_animation_container(bool has_container, Object *ob) { - if (!has_container) { - char anim_id[200]; - sprintf(anim_id, "action_container-%s", translate_id(id_name(ob)).c_str()); - openAnimation(anim_id, encode_xml(id_name(ob))); - } - return true; + if (!has_container) { + char anim_id[200]; + sprintf(anim_id, "action_container-%s", translate_id(id_name(ob)).c_str()); + openAnimation(anim_id, encode_xml(id_name(ob))); + } + return true; } void AnimationExporter::openAnimationWithClip(std::string action_id, std::string action_name) { - std::vector<std::string> anim_meta_entry; - anim_meta_entry.push_back(translate_id(action_id)); - anim_meta_entry.push_back(action_name); - anim_meta.push_back(anim_meta_entry); + std::vector<std::string> anim_meta_entry; + anim_meta_entry.push_back(translate_id(action_id)); + anim_meta_entry.push_back(action_name); + anim_meta.push_back(anim_meta_entry); - openAnimation(translate_id(action_id), action_name); + openAnimation(translate_id(action_id), action_name); } void AnimationExporter::close_animation_container(bool has_container) { - if (has_container) - closeAnimation(); + if (has_container) + closeAnimation(); } bool AnimationExporter::exportAnimations() { - Scene *sce = blender_context.get_scene(); - - LinkNode &export_set = *this->export_settings->export_set; - bool has_anim_data = bc_has_animations(sce, export_set); - int animation_count = 0; - if (has_anim_data) { - - BCObjectSet animated_subset; - BCAnimationSampler::get_animated_from_export_set(animated_subset, export_set); - animation_count = animated_subset.size(); - BCAnimationSampler animation_sampler(blender_context, animated_subset); - - try { - animation_sampler.sample_scene( - export_settings->sampling_rate, - /*keyframe_at_end = */ true, - export_settings->open_sim, - export_settings->keep_keyframes, - export_settings->export_animation_type - ); - - openLibrary(); - - BCObjectSet::iterator it; - for (it = animated_subset.begin(); it != animated_subset.end(); ++it) { - Object *ob = *it; - exportAnimation(ob, animation_sampler); - } - } - catch (std::invalid_argument &iae) - { - fprintf(stderr, "Animation export interrupted"); - fprintf(stderr, "Exception was: %s", iae.what()); - } - - closeLibrary(); + Scene *sce = blender_context.get_scene(); + + LinkNode &export_set = *this->export_settings->export_set; + bool has_anim_data = bc_has_animations(sce, export_set); + int animation_count = 0; + if (has_anim_data) { + + BCObjectSet animated_subset; + BCAnimationSampler::get_animated_from_export_set(animated_subset, export_set); + animation_count = animated_subset.size(); + BCAnimationSampler animation_sampler(blender_context, animated_subset); + + try { + animation_sampler.sample_scene(export_settings->sampling_rate, + /*keyframe_at_end = */ true, + export_settings->open_sim, + export_settings->keep_keyframes, + export_settings->export_animation_type); + + openLibrary(); + + BCObjectSet::iterator it; + for (it = animated_subset.begin(); it != animated_subset.end(); ++it) { + Object *ob = *it; + exportAnimation(ob, animation_sampler); + } + } + catch (std::invalid_argument &iae) { + fprintf(stderr, "Animation export interrupted"); + fprintf(stderr, "Exception was: %s", iae.what()); + } + + closeLibrary(); #if 0 - /* TODO: If all actions shall be exported, we need to call the - * AnimationClipExporter which will figure out which actions - * need to be exported for which objects - */ - if (this->export_settings->include_all_actions) { - AnimationClipExporter ace(eval_ctx, sw, export_settings, anim_meta); - ace.exportAnimationClips(sce); - } + /* TODO: If all actions shall be exported, we need to call the + * AnimationClipExporter which will figure out which actions + * need to be exported for which objects + */ + if (this->export_settings->include_all_actions) { + AnimationClipExporter ace(eval_ctx, sw, export_settings, anim_meta); + ace.exportAnimationClips(sce); + } #endif - } - return animation_count; + } + return animation_count; } /* called for each exported object */ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler) { - bool container_is_open = false; + bool container_is_open = false; - //Transform animations (trans, rot, scale) - container_is_open = open_animation_container(container_is_open, ob); + //Transform animations (trans, rot, scale) + container_is_open = open_animation_container(container_is_open, ob); - /* Now take care of the Object Animations - * Note: For Armatures the skeletal animation has already been exported (see above) - * However Armatures also can have Object animation. - */ - bool export_as_matrix = this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX; + /* Now take care of the Object Animations + * Note: For Armatures the skeletal animation has already been exported (see above) + * However Armatures also can have Object animation. + */ + bool export_as_matrix = this->export_settings->export_transformation_type == + BC_TRANSFORMATION_TYPE_MATRIX; - if (export_as_matrix) { - export_matrix_animation(ob, sampler); // export all transform_curves as one single matrix animation - } + if (export_as_matrix) { + export_matrix_animation( + ob, sampler); // export all transform_curves as one single matrix animation + } - export_curve_animation_set(ob, sampler, export_as_matrix); + export_curve_animation_set(ob, sampler, export_as_matrix); - if (ob->type == OB_ARMATURE) { + if (ob->type == OB_ARMATURE) { #ifdef WITH_MORPH_ANIMATION - /* TODO: This needs to be handled by extra profiles, postponed for now */ - export_morph_animation(ob); + /* TODO: This needs to be handled by extra profiles, postponed for now */ + export_morph_animation(ob); #endif - /* Export skeletal animation (if any) */ - bArmature *arm = (bArmature *)ob->data; - for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next) - export_bone_animations_recursive(ob, root_bone, sampler); - } + /* Export skeletal animation (if any) */ + bArmature *arm = (bArmature *)ob->data; + for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next) + export_bone_animations_recursive(ob, root_bone, sampler); + } - close_animation_container(container_is_open); + close_animation_container(container_is_open); } /* @@ -175,88 +173,92 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler) * And when parent inverse matrices are involved (when exporting * object hierarchies) */ -void AnimationExporter::export_curve_animation_set(Object *ob, BCAnimationSampler &sampler, bool export_as_matrix) +void AnimationExporter::export_curve_animation_set(Object *ob, + BCAnimationSampler &sampler, + bool export_as_matrix) { - BCAnimationCurveMap *curves = sampler.get_curves(ob); - bool keep_flat_curves = this->export_settings->keep_flat_curves; - - BCAnimationCurveMap::iterator it; - for (it = curves->begin(); it != curves->end(); ++it) { - BCAnimationCurve &curve = *it->second; - if (curve.get_channel_target() == "rotation_quaternion") { - /* - Can not export Quaternion animation in Collada as far as i know) - Maybe automatically convert to euler rotation? - Discard for now. - */ - continue; - } - - if (export_as_matrix && curve.is_transform_curve()) { - /* All Transform curves will be exported within a single matrix animation, - * see export_matrix_animation() - * No need to export the curves here again. - */ - continue; - } - - if (!keep_flat_curves && !curve.is_animated()) { - continue; - } - - BCAnimationCurve *mcurve = get_modified_export_curve(ob, curve, *curves); - if (mcurve) { - export_curve_animation(ob, *mcurve); - delete mcurve; - } - else { - export_curve_animation(ob, curve); - } - } + BCAnimationCurveMap *curves = sampler.get_curves(ob); + bool keep_flat_curves = this->export_settings->keep_flat_curves; + + BCAnimationCurveMap::iterator it; + for (it = curves->begin(); it != curves->end(); ++it) { + BCAnimationCurve &curve = *it->second; + if (curve.get_channel_target() == "rotation_quaternion") { + /* + Can not export Quaternion animation in Collada as far as i know) + Maybe automatically convert to euler rotation? + Discard for now. + */ + continue; + } + + if (export_as_matrix && curve.is_transform_curve()) { + /* All Transform curves will be exported within a single matrix animation, + * see export_matrix_animation() + * No need to export the curves here again. + */ + continue; + } + + if (!keep_flat_curves && !curve.is_animated()) { + continue; + } + + BCAnimationCurve *mcurve = get_modified_export_curve(ob, curve, *curves); + if (mcurve) { + export_curve_animation(ob, *mcurve); + delete mcurve; + } + else { + export_curve_animation(ob, curve); + } + } } void AnimationExporter::export_matrix_animation(Object *ob, BCAnimationSampler &sampler) { - bool keep_flat_curves = this->export_settings->keep_flat_curves; - - std::vector<float> frames; - sampler.get_object_frames(frames, ob); - if (frames.size() > 0) { - BCMatrixSampleMap samples; - bool is_animated = sampler.get_object_samples(samples, ob); - if (keep_flat_curves || is_animated) { - bAction *action = bc_getSceneObjectAction(ob); - std::string name = encode_xml(id_name(ob)); - std::string action_name = (action == NULL) ? name + "-action" : id_name(action); - std::string channel_type = "transform"; - std::string axis = ""; - std::string id = bc_get_action_id(action_name, name, channel_type, axis); - - std::string target = translate_id(name) + '/' + channel_type; - - export_collada_matrix_animation(id, name, target, frames, samples); - } - } + bool keep_flat_curves = this->export_settings->keep_flat_curves; + + std::vector<float> frames; + sampler.get_object_frames(frames, ob); + if (frames.size() > 0) { + BCMatrixSampleMap samples; + bool is_animated = sampler.get_object_samples(samples, ob); + if (keep_flat_curves || is_animated) { + bAction *action = bc_getSceneObjectAction(ob); + std::string name = encode_xml(id_name(ob)); + std::string action_name = (action == NULL) ? name + "-action" : id_name(action); + std::string channel_type = "transform"; + std::string axis = ""; + std::string id = bc_get_action_id(action_name, name, channel_type, axis); + + std::string target = translate_id(name) + '/' + channel_type; + + export_collada_matrix_animation(id, name, target, frames, samples); + } + } } //write bone animations in transform matrix sources -void AnimationExporter::export_bone_animations_recursive(Object *ob, Bone *bone, BCAnimationSampler &sampler) +void AnimationExporter::export_bone_animations_recursive(Object *ob, + Bone *bone, + BCAnimationSampler &sampler) { - bool keep_flat_curves = this->export_settings->keep_flat_curves; + bool keep_flat_curves = this->export_settings->keep_flat_curves; - std::vector<float> frames; - sampler.get_bone_frames(frames, ob, bone); + std::vector<float> frames; + sampler.get_bone_frames(frames, ob, bone); - if (frames.size()) { - BCMatrixSampleMap samples; - bool is_animated = sampler.get_bone_samples(samples, ob, bone); - if (keep_flat_curves || is_animated) { - export_bone_animation(ob, bone, frames, samples); - } - } + if (frames.size()) { + BCMatrixSampleMap samples; + bool is_animated = sampler.get_bone_samples(samples, ob, bone); + if (keep_flat_curves || is_animated) { + export_bone_animation(ob, bone, frames, samples); + } + } - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) - export_bone_animations_recursive(ob, child, sampler); + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) + export_bone_animations_recursive(ob, child, sampler); } /** @@ -267,511 +269,535 @@ void AnimationExporter::export_bone_animations_recursive(Object *ob, Bone *bone, * IMPORTANT: the modified curve must be deleted by the caller when no longer needed * if no conversion is needed this method returns a NULL; */ -BCAnimationCurve *AnimationExporter::get_modified_export_curve(Object *ob, BCAnimationCurve &curve, BCAnimationCurveMap &curves) +BCAnimationCurve *AnimationExporter::get_modified_export_curve(Object *ob, + BCAnimationCurve &curve, + BCAnimationCurveMap &curves) { - std::string channel_target = curve.get_channel_target(); - BCAnimationCurve *mcurve = NULL; - if (channel_target == "lens") { - - /* Create an xfov curve */ - - BCCurveKey key(BC_ANIMATION_TYPE_CAMERA, "xfov", 0); - mcurve = new BCAnimationCurve(key, ob); - - // now tricky part: transform the fcurve - BCValueMap lens_values; - curve.get_value_map(lens_values); - - BCAnimationCurve *sensor_curve = NULL; - BCCurveKey sensor_key(BC_ANIMATION_TYPE_CAMERA, "sensor_width", 0); - BCAnimationCurveMap::iterator cit = curves.find(sensor_key); - if (cit != curves.end()) { - sensor_curve = cit->second; - } - - BCValueMap::const_iterator vit; - for (vit = lens_values.begin(); vit != lens_values.end(); ++vit) { - int frame = vit->first; - float lens_value = vit->second; - - float sensor_value; - if (sensor_curve) { - sensor_value = sensor_curve->get_value(frame); - } - else { - sensor_value = ((Camera *)ob->data)->sensor_x; - } - float value = RAD2DEGF(focallength_to_fov(lens_value, sensor_value)); - mcurve->add_value(value, frame); - } - mcurve->clean_handles(); // to reset the handles - } - return mcurve; + std::string channel_target = curve.get_channel_target(); + BCAnimationCurve *mcurve = NULL; + if (channel_target == "lens") { + + /* Create an xfov curve */ + + BCCurveKey key(BC_ANIMATION_TYPE_CAMERA, "xfov", 0); + mcurve = new BCAnimationCurve(key, ob); + + // now tricky part: transform the fcurve + BCValueMap lens_values; + curve.get_value_map(lens_values); + + BCAnimationCurve *sensor_curve = NULL; + BCCurveKey sensor_key(BC_ANIMATION_TYPE_CAMERA, "sensor_width", 0); + BCAnimationCurveMap::iterator cit = curves.find(sensor_key); + if (cit != curves.end()) { + sensor_curve = cit->second; + } + + BCValueMap::const_iterator vit; + for (vit = lens_values.begin(); vit != lens_values.end(); ++vit) { + int frame = vit->first; + float lens_value = vit->second; + + float sensor_value; + if (sensor_curve) { + sensor_value = sensor_curve->get_value(frame); + } + else { + sensor_value = ((Camera *)ob->data)->sensor_x; + } + float value = RAD2DEGF(focallength_to_fov(lens_value, sensor_value)); + mcurve->add_value(value, frame); + } + mcurve->clean_handles(); // to reset the handles + } + return mcurve; } -void AnimationExporter::export_curve_animation( - Object *ob, - BCAnimationCurve &curve) +void AnimationExporter::export_curve_animation(Object *ob, BCAnimationCurve &curve) { - std::string channel_target = curve.get_channel_target(); - - /* - * Some curves can not be exported as is and need some conversion - * For more information see implementation oif get_modified_export_curve() - * note: if mcurve is not NULL then it must be deleted at end of this method; - */ - - int channel_index = curve.get_channel_index(); - std::string axis = get_axis_name(channel_target, channel_index); // RGB or XYZ or "" - - std::string action_name; - bAction *action = bc_getSceneObjectAction(ob); - action_name = (action) ? id_name(action) : "constraint_anim"; - - const std::string curve_name = encode_xml(curve.get_animation_name(ob)); - std::string id = bc_get_action_id(action_name, curve_name, channel_target, axis, "."); - - std::string collada_target = translate_id(curve_name); - - if (curve.is_of_animation_type(BC_ANIMATION_TYPE_MATERIAL)) { - int material_index = curve.get_subindex(); - Material *ma = give_current_material(ob, material_index + 1); - if (ma) { - collada_target = translate_id(id_name(ma)) + "-effect/common/" + get_collada_sid(curve, axis); - } - } - else { - collada_target += "/" + get_collada_sid(curve, axis); - } - - export_collada_curve_animation(id, curve_name, collada_target, axis, curve); - + std::string channel_target = curve.get_channel_target(); + + /* + * Some curves can not be exported as is and need some conversion + * For more information see implementation oif get_modified_export_curve() + * note: if mcurve is not NULL then it must be deleted at end of this method; + */ + + int channel_index = curve.get_channel_index(); + std::string axis = get_axis_name(channel_target, channel_index); // RGB or XYZ or "" + + std::string action_name; + bAction *action = bc_getSceneObjectAction(ob); + action_name = (action) ? id_name(action) : "constraint_anim"; + + const std::string curve_name = encode_xml(curve.get_animation_name(ob)); + std::string id = bc_get_action_id(action_name, curve_name, channel_target, axis, "."); + + std::string collada_target = translate_id(curve_name); + + if (curve.is_of_animation_type(BC_ANIMATION_TYPE_MATERIAL)) { + int material_index = curve.get_subindex(); + Material *ma = give_current_material(ob, material_index + 1); + if (ma) { + collada_target = translate_id(id_name(ma)) + "-effect/common/" + + get_collada_sid(curve, axis); + } + } + else { + collada_target += "/" + get_collada_sid(curve, axis); + } + + export_collada_curve_animation(id, curve_name, collada_target, axis, curve); } -void AnimationExporter::export_bone_animation(Object *ob, Bone *bone, BCFrames &frames, BCMatrixSampleMap &samples) +void AnimationExporter::export_bone_animation(Object *ob, + Bone *bone, + BCFrames &frames, + BCMatrixSampleMap &samples) { - bAction* action = bc_getSceneObjectAction(ob); - std::string bone_name(bone->name); - std::string name = encode_xml(id_name(ob)); - std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix"); - std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform"; + bAction *action = bc_getSceneObjectAction(ob); + std::string bone_name(bone->name); + std::string name = encode_xml(id_name(ob)); + std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix"); + std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform"; - export_collada_matrix_animation(id, name, target, frames, samples); + export_collada_matrix_animation(id, name, target, frames, samples); } bool AnimationExporter::is_bone_deform_group(Bone *bone) { - bool is_def; - //Check if current bone is deform - if ((bone->flag & BONE_NO_DEFORM) == 0) return true; - //Check child bones - else { - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - //loop through all the children until deform bone is found, and then return - is_def = is_bone_deform_group(child); - if (is_def) return true; - } - } - //no deform bone found in children also - return false; + bool is_def; + //Check if current bone is deform + if ((bone->flag & BONE_NO_DEFORM) == 0) + return true; + //Check child bones + else { + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + //loop through all the children until deform bone is found, and then return + is_def = is_bone_deform_group(child); + if (is_def) + return true; + } + } + //no deform bone found in children also + return false; } - -void AnimationExporter::export_collada_curve_animation( - std::string id, - std::string name, - std::string collada_target, - std::string axis, - BCAnimationCurve &curve) +void AnimationExporter::export_collada_curve_animation(std::string id, + std::string name, + std::string collada_target, + std::string axis, + BCAnimationCurve &curve) { - BCFrames frames; - BCValues values; - curve.get_frames(frames); - curve.get_values(values); - std::string channel_target = curve.get_channel_target(); - - fprintf(stdout, "Export animation curve %s (%d control points)\n", id.c_str(), int(frames.size())); - openAnimation(id, name); - BC_animation_source_type source_type = (curve.is_rotation_curve()) ? BC_SOURCE_TYPE_ANGLE : BC_SOURCE_TYPE_VALUE; - - std::string input_id = collada_source_from_values(BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, axis); - std::string output_id = collada_source_from_values(source_type, COLLADASW::InputSemantic::OUTPUT, values, id, axis); - - bool has_tangents = false; - std::string interpolation_id; - if (this->export_settings->keep_smooth_curves) - interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents); - else - interpolation_id = collada_linear_interpolation_source(frames.size(), id); - - std::string intangent_id; - std::string outtangent_id; - if (has_tangents) { - intangent_id = collada_tangent_from_curve(COLLADASW::InputSemantic::IN_TANGENT, curve, id, axis); - outtangent_id = collada_tangent_from_curve(COLLADASW::InputSemantic::OUT_TANGENT, curve, id, axis); - } - - std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX; - - COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); - - sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id)); - sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id)); - sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(EMPTY_STRING, interpolation_id)); - - if (has_tangents) { - sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(EMPTY_STRING, intangent_id)); - sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(EMPTY_STRING, outtangent_id)); - } - - addSampler(sampler); - addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), collada_target); - - closeAnimation(); + BCFrames frames; + BCValues values; + curve.get_frames(frames); + curve.get_values(values); + std::string channel_target = curve.get_channel_target(); + + fprintf( + stdout, "Export animation curve %s (%d control points)\n", id.c_str(), int(frames.size())); + openAnimation(id, name); + BC_animation_source_type source_type = (curve.is_rotation_curve()) ? BC_SOURCE_TYPE_ANGLE : + BC_SOURCE_TYPE_VALUE; + + std::string input_id = collada_source_from_values( + BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, axis); + std::string output_id = collada_source_from_values( + source_type, COLLADASW::InputSemantic::OUTPUT, values, id, axis); + + bool has_tangents = false; + std::string interpolation_id; + if (this->export_settings->keep_smooth_curves) + interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents); + else + interpolation_id = collada_linear_interpolation_source(frames.size(), id); + + std::string intangent_id; + std::string outtangent_id; + if (has_tangents) { + intangent_id = collada_tangent_from_curve( + COLLADASW::InputSemantic::IN_TANGENT, curve, id, axis); + outtangent_id = collada_tangent_from_curve( + COLLADASW::InputSemantic::OUT_TANGENT, curve, id, axis); + } + + std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX; + + COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); + + sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id)); + sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id)); + sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, + COLLADABU::URI(EMPTY_STRING, interpolation_id)); + + if (has_tangents) { + sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, + COLLADABU::URI(EMPTY_STRING, intangent_id)); + sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, + COLLADABU::URI(EMPTY_STRING, outtangent_id)); + } + + addSampler(sampler); + addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), collada_target); + + closeAnimation(); } -void AnimationExporter::export_collada_matrix_animation(std::string id, std::string name, std::string target, BCFrames &frames, BCMatrixSampleMap &samples) +void AnimationExporter::export_collada_matrix_animation(std::string id, + std::string name, + std::string target, + BCFrames &frames, + BCMatrixSampleMap &samples) { - fprintf(stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size())); - - openAnimationWithClip(id, name); + fprintf( + stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size())); - std::string input_id = collada_source_from_values(BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, ""); - std::string output_id = collada_source_from_values(samples, id); - std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id); + openAnimationWithClip(id, name); - std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX; - COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); + std::string input_id = collada_source_from_values( + BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, ""); + std::string output_id = collada_source_from_values(samples, id); + std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id); + std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); - sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id)); - sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id)); - sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(EMPTY_STRING, interpolation_id)); + sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id)); + sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id)); + sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, + COLLADABU::URI(EMPTY_STRING, interpolation_id)); - // Matrix animation has no tangents + // Matrix animation has no tangents - addSampler(sampler); - addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), target); + addSampler(sampler); + addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), target); - closeAnimation(); + closeAnimation(); } std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic) { - switch (semantic) { - case COLLADASW::InputSemantic::INPUT: - return INPUT_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::OUTPUT: - return OUTPUT_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::INTERPOLATION: - return INTERPOLATION_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::IN_TANGENT: - return INTANGENT_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::OUT_TANGENT: - return OUTTANGENT_SOURCE_ID_SUFFIX; - default: - break; - } - return ""; + switch (semantic) { + case COLLADASW::InputSemantic::INPUT: + return INPUT_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::OUTPUT: + return OUTPUT_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::INTERPOLATION: + return INTERPOLATION_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::IN_TANGENT: + return INTANGENT_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::OUT_TANGENT: + return OUTTANGENT_SOURCE_ID_SUFFIX; + default: + break; + } + return ""; } -void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, - COLLADASW::InputSemantic::Semantics semantic, - bool is_rot, - const std::string axis, - bool transform) +void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList ¶m, + COLLADASW::InputSemantic::Semantics semantic, + bool is_rot, + const std::string axis, + bool transform) { - switch (semantic) { - case COLLADASW::InputSemantic::INPUT: - param.push_back("TIME"); - break; - case COLLADASW::InputSemantic::OUTPUT: - if (is_rot) { - param.push_back("ANGLE"); - } - else { - if (axis != "") { - param.push_back(axis); - } - else - if (transform) { - param.push_back("TRANSFORM"); - } - else { //assumes if axis isn't specified all axises are added - param.push_back("X"); - param.push_back("Y"); - param.push_back("Z"); - } - } - break; - case COLLADASW::InputSemantic::IN_TANGENT: - case COLLADASW::InputSemantic::OUT_TANGENT: - param.push_back("X"); - param.push_back("Y"); - break; - default: - break; - } + switch (semantic) { + case COLLADASW::InputSemantic::INPUT: + param.push_back("TIME"); + break; + case COLLADASW::InputSemantic::OUTPUT: + if (is_rot) { + param.push_back("ANGLE"); + } + else { + if (axis != "") { + param.push_back(axis); + } + else if (transform) { + param.push_back("TRANSFORM"); + } + else { //assumes if axis isn't specified all axises are added + param.push_back("X"); + param.push_back("Y"); + param.push_back("Z"); + } + } + break; + case COLLADASW::InputSemantic::IN_TANGENT: + case COLLADASW::InputSemantic::OUT_TANGENT: + param.push_back("X"); + param.push_back("Y"); + break; + default: + break; + } } -std::string AnimationExporter::collada_tangent_from_curve(COLLADASW::InputSemantic::Semantics semantic, BCAnimationCurve &curve, const std::string& anim_id, std::string axis_name) +std::string AnimationExporter::collada_tangent_from_curve( + COLLADASW::InputSemantic::Semantics semantic, + BCAnimationCurve &curve, + const std::string &anim_id, + std::string axis_name) { - Scene *scene = blender_context.get_scene(); - std::string channel = curve.get_channel_target(); + Scene *scene = blender_context.get_scene(); + std::string channel = curve.get_channel_target(); - const std::string source_id = anim_id + get_semantic_suffix(semantic); + const std::string source_id = anim_id + get_semantic_suffix(semantic); - bool is_angle = (bc_startswith(channel, "rotation") || channel == "spot_size"); + bool is_angle = (bc_startswith(channel, "rotation") || channel == "spot_size"); - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(curve.sample_count()); - source.setAccessorStride(2); + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(curve.sample_count()); + source.setAccessorStride(2); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - add_source_parameters(param, semantic, is_angle, axis_name, false); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, is_angle, axis_name, false); - source.prepareToAppendValues(); + source.prepareToAppendValues(); - const FCurve *fcu = curve.get_fcurve(); - int tangent = (semantic == COLLADASW::InputSemantic::IN_TANGENT) ? 0 : 2; + const FCurve *fcu = curve.get_fcurve(); + int tangent = (semantic == COLLADASW::InputSemantic::IN_TANGENT) ? 0 : 2; - for (int i = 0; i < fcu->totvert; ++i) { - BezTriple &bezt = fcu->bezt[i]; + for (int i = 0; i < fcu->totvert; ++i) { + BezTriple &bezt = fcu->bezt[i]; - float sampled_time = bezt.vec[tangent][0]; - float sampled_val = bezt.vec[tangent][1]; + float sampled_time = bezt.vec[tangent][0]; + float sampled_val = bezt.vec[tangent][1]; - if (is_angle) { - sampled_val = RAD2DEGF(sampled_val); - } + if (is_angle) { + sampled_val = RAD2DEGF(sampled_val); + } - source.appendValues(FRA2TIME(sampled_time)); - source.appendValues(sampled_val); - - } - source.finish(); - return source_id; + source.appendValues(FRA2TIME(sampled_time)); + source.appendValues(sampled_val); + } + source.finish(); + return source_id; } std::string AnimationExporter::collada_source_from_values( - BC_animation_source_type source_type, - COLLADASW::InputSemantic::Semantics semantic, - std::vector<float> &values, - const std::string& anim_id, - const std::string axis_name) + BC_animation_source_type source_type, + COLLADASW::InputSemantic::Semantics semantic, + std::vector<float> &values, + const std::string &anim_id, + const std::string axis_name) { - Scene *scene = blender_context.get_scene(); - /* T can be float, int or double */ - - int stride = 1; - int entry_count = values.size() / stride; - std::string source_id = anim_id + get_semantic_suffix(semantic); - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(entry_count); - source.setAccessorStride(stride); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - add_source_parameters(param, semantic, source_type== BC_SOURCE_TYPE_ANGLE, axis_name, false); - - source.prepareToAppendValues(); - - for (int i = 0; i < entry_count; i++) { - float val = values[i]; - switch (source_type) { - case BC_SOURCE_TYPE_TIMEFRAME: - val = FRA2TIME(val); - break; - case BC_SOURCE_TYPE_ANGLE: - val = RAD2DEGF(val); - break; - default: break; - } - source.appendValues(val); - } - - source.finish(); - - return source_id; + Scene *scene = blender_context.get_scene(); + /* T can be float, int or double */ + + int stride = 1; + int entry_count = values.size() / stride; + std::string source_id = anim_id + get_semantic_suffix(semantic); + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(entry_count); + source.setAccessorStride(stride); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, source_type == BC_SOURCE_TYPE_ANGLE, axis_name, false); + + source.prepareToAppendValues(); + + for (int i = 0; i < entry_count; i++) { + float val = values[i]; + switch (source_type) { + case BC_SOURCE_TYPE_TIMEFRAME: + val = FRA2TIME(val); + break; + case BC_SOURCE_TYPE_ANGLE: + val = RAD2DEGF(val); + break; + default: + break; + } + source.appendValues(val); + } + + source.finish(); + + return source_id; } /* * Create a collada matrix source for a set of samples */ -std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &samples, const std::string &anim_id) +std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &samples, + const std::string &anim_id) { - COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; - std::string source_id = anim_id + get_semantic_suffix(semantic); - - COLLADASW::Float4x4Source source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(samples.size()); - source.setAccessorStride(16); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - add_source_parameters(param, semantic, false, "", true); - - source.prepareToAppendValues(); - - BCMatrixSampleMap::iterator it; - int precision = (this->export_settings->limit_precision) ? 6 : -1; // could be made configurable - for (it = samples.begin(); it != samples.end(); it++) { - const BCMatrix *sample = it->second; - double daemat[4][4]; - sample->get_matrix(daemat, true, precision); - source.appendValues(daemat); - } - - source.finish(); - return source_id; + COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; + std::string source_id = anim_id + get_semantic_suffix(semantic); + + COLLADASW::Float4x4Source source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(samples.size()); + source.setAccessorStride(16); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, false, "", true); + + source.prepareToAppendValues(); + + BCMatrixSampleMap::iterator it; + int precision = (this->export_settings->limit_precision) ? 6 : -1; // could be made configurable + for (it = samples.begin(); it != samples.end(); it++) { + const BCMatrix *sample = it->second; + double daemat[4][4]; + sample->get_matrix(daemat, true, precision); + source.appendValues(daemat); + } + + source.finish(); + return source_id; } std::string AnimationExporter::collada_interpolation_source(const BCAnimationCurve &curve, - const std::string& anim_id, - const std::string axis, - bool *has_tangents) + const std::string &anim_id, + const std::string axis, + bool *has_tangents) { - std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); - - COLLADASW::NameSource source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(curve.sample_count()); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("INTERPOLATION"); - - source.prepareToAppendValues(); - - *has_tangents = false; - - std::vector<float>frames; - curve.get_frames(frames); - - for (unsigned int i = 0; i < curve.sample_count(); i++) { - float frame = frames[i]; - int ipo = curve.get_interpolation_type(frame); - if (ipo == BEZT_IPO_BEZ) { - source.appendValues(BEZIER_NAME); - *has_tangents = true; - } - else if (ipo == BEZT_IPO_CONST) { - source.appendValues(STEP_NAME); - } - else { // BEZT_IPO_LIN - source.appendValues(LINEAR_NAME); - } - } - // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS - - source.finish(); - - return source_id; + std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); + + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(curve.sample_count()); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("INTERPOLATION"); + + source.prepareToAppendValues(); + + *has_tangents = false; + + std::vector<float> frames; + curve.get_frames(frames); + + for (unsigned int i = 0; i < curve.sample_count(); i++) { + float frame = frames[i]; + int ipo = curve.get_interpolation_type(frame); + if (ipo == BEZT_IPO_BEZ) { + source.appendValues(BEZIER_NAME); + *has_tangents = true; + } + else if (ipo == BEZT_IPO_CONST) { + source.appendValues(STEP_NAME); + } + else { // BEZT_IPO_LIN + source.appendValues(LINEAR_NAME); + } + } + // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS + + source.finish(); + + return source_id; } -std::string AnimationExporter::collada_linear_interpolation_source(int tot, const std::string& anim_id) +std::string AnimationExporter::collada_linear_interpolation_source(int tot, + const std::string &anim_id) { - std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); + std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); - COLLADASW::NameSource source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(tot); - source.setAccessorStride(1); + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(tot); + source.setAccessorStride(1); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("INTERPOLATION"); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("INTERPOLATION"); - source.prepareToAppendValues(); + source.prepareToAppendValues(); - for (int i = 0; i < tot; i++) { - source.appendValues(LINEAR_NAME); - } + for (int i = 0; i < tot; i++) { + source.appendValues(LINEAR_NAME); + } - source.finish(); + source.finish(); - return source_id; + return source_id; } const std::string AnimationExporter::get_collada_name(std::string channel_target) const { - /* - * Translation table to map FCurve animation types to Collada animation. - * Todo: Maybe we can keep the names from the fcurves here instead of - * mapping. However this is what i found in the old code. So keep - * this map for now. - */ - static std::map<std::string, std::string> BC_CHANNEL_BLENDER_TO_COLLADA = { - { "rotation", "rotation" }, - { "rotation_euler", "rotation" }, - { "rotation_quaternion", "rotation" }, - { "scale", "scale" }, - { "location", "location" }, - - /* Materials */ - { "specular_color", "specular" }, - { "diffuse_color", "diffuse" }, - { "ior", "index_of_refraction" }, - { "specular_hardness", "specular_hardness" }, - { "alpha", "alpha" }, - - /* Lights */ - { "color", "color" }, - { "fall_off_angle", "falloff_angle" }, - { "spot_size", "falloff_angle" }, - { "fall_off_exponent", "falloff_exponent" }, - { "spot_blend", "falloff_exponent" }, - { "blender/blender_dist", "blender/blender_dist" }, // special blender profile (todo: make this more elegant) - { "distance", "blender/blender_dist" }, // special blender profile (todo: make this more elegant) - - /* Cameras */ - { "lens", "xfov" }, - { "xfov", "xfov" }, - { "xmag", "xmag" }, - { "zfar", "zfar" }, - { "znear", "znear" }, - { "ortho_scale", "xmag" }, - { "clip_end", "zfar" }, - { "clip_start", "znear" } - }; - - std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find(channel_target); - if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end()) - return ""; - - std::string tm_name = name_it->second; - return tm_name; + /* + * Translation table to map FCurve animation types to Collada animation. + * Todo: Maybe we can keep the names from the fcurves here instead of + * mapping. However this is what i found in the old code. So keep + * this map for now. + */ + static std::map<std::string, std::string> BC_CHANNEL_BLENDER_TO_COLLADA = { + {"rotation", "rotation"}, + {"rotation_euler", "rotation"}, + {"rotation_quaternion", "rotation"}, + {"scale", "scale"}, + {"location", "location"}, + + /* Materials */ + {"specular_color", "specular"}, + {"diffuse_color", "diffuse"}, + {"ior", "index_of_refraction"}, + {"specular_hardness", "specular_hardness"}, + {"alpha", "alpha"}, + + /* Lights */ + {"color", "color"}, + {"fall_off_angle", "falloff_angle"}, + {"spot_size", "falloff_angle"}, + {"fall_off_exponent", "falloff_exponent"}, + {"spot_blend", "falloff_exponent"}, + {"blender/blender_dist", + "blender/blender_dist"}, // special blender profile (todo: make this more elegant) + {"distance", + "blender/blender_dist"}, // special blender profile (todo: make this more elegant) + + /* Cameras */ + {"lens", "xfov"}, + {"xfov", "xfov"}, + {"xmag", "xmag"}, + {"zfar", "zfar"}, + {"znear", "znear"}, + {"ortho_scale", "xmag"}, + {"clip_end", "zfar"}, + {"clip_start", "znear"}}; + + std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find( + channel_target); + if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end()) + return ""; + + std::string tm_name = name_it->second; + return tm_name; } /* * Assign sid of the animated parameter or transform for rotation, * axis name is always appended and the value of append_axis is ignored */ -std::string AnimationExporter::get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name) +std::string AnimationExporter::get_collada_sid(const BCAnimationCurve &curve, + const std::string axis_name) { - std::string channel_target = curve.get_channel_target(); - std::string tm_name = get_collada_name(channel_target); - - bool is_angle = curve.is_rotation_curve(); + std::string channel_target = curve.get_channel_target(); + std::string tm_name = get_collada_name(channel_target); + bool is_angle = curve.is_rotation_curve(); - if (tm_name.size()) { - if (is_angle) - return tm_name + std::string(axis_name) + ".ANGLE"; - else - if (axis_name != "") - return tm_name + "." + std::string(axis_name); - else - return tm_name; - } + if (tm_name.size()) { + if (is_angle) + return tm_name + std::string(axis_name) + ".ANGLE"; + else if (axis_name != "") + return tm_name + "." + std::string(axis_name); + else + return tm_name; + } - return tm_name; + return tm_name; } #ifdef WITH_MORPH_ANIMATION @@ -780,21 +806,21 @@ So we have to update BCSample for this to work. */ void AnimationExporter::export_morph_animation(Object *ob, BCAnimationSampler &sampler) { - FCurve *fcu; - Key *key = BKE_key_from_object(ob); - if (!key) return; - - if (key->adt && key->adt->action) { - fcu = (FCurve *)key->adt->action->curves.first; + FCurve *fcu; + Key *key = BKE_key_from_object(ob); + if (!key) + return; - while (fcu) { - BC_animation_transform_type tm_type = get_transform_type(fcu->rna_path); + if (key->adt && key->adt->action) { + fcu = (FCurve *)key->adt->action->curves.first; - create_keyframed_animation(ob, fcu, tm_type, true, sampler); + while (fcu) { + BC_animation_transform_type tm_type = get_transform_type(fcu->rna_path); - fcu = fcu->next; - } - } + create_keyframed_animation(ob, fcu, tm_type, true, sampler); + fcu = fcu->next; + } + } } #endif diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index fa0640c73e8..71d7d14a112 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -23,8 +23,7 @@ #include "BCAnimationCurve.h" -extern "C" -{ +extern "C" { #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_anim_types.h" @@ -45,7 +44,7 @@ extern "C" #include "BKE_fcurve.h" #include "BKE_animsys.h" #include "BKE_scene.h" -#include "BKE_action.h" // pose functions +#include "BKE_action.h" // pose functions #include "BKE_armature.h" #include "BKE_object.h" #include "BKE_constraint.h" @@ -77,185 +76,185 @@ extern "C" #include <vector> #include <map> -#include <algorithm> // std::find +#include <algorithm> // std::find struct Depsgraph; typedef enum BC_animation_source_type { - BC_SOURCE_TYPE_VALUE, - BC_SOURCE_TYPE_ANGLE, - BC_SOURCE_TYPE_TIMEFRAME, + BC_SOURCE_TYPE_VALUE, + BC_SOURCE_TYPE_ANGLE, + BC_SOURCE_TYPE_TIMEFRAME, } BC_animation_source_type; -class AnimationExporter: COLLADASW::LibraryAnimations -{ -private: - BlenderContext &blender_context; - COLLADASW::StreamWriter *sw; - const ExportSettings *export_settings; +class AnimationExporter : COLLADASW::LibraryAnimations { + private: + BlenderContext &blender_context; + COLLADASW::StreamWriter *sw; + const ExportSettings *export_settings; -public: + public: + AnimationExporter(BlenderContext &blender_context, + COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings) + : COLLADASW::LibraryAnimations(sw), + blender_context(blender_context), + sw(sw), + export_settings(export_settings) + { + } - AnimationExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings): - COLLADASW::LibraryAnimations(sw), - blender_context(blender_context), - sw(sw), - export_settings(export_settings) - {} + bool exportAnimations(); - bool exportAnimations(); + // called for each exported object + void operator()(Object *ob); - // called for each exported object - void operator() (Object *ob); + protected: + void export_object_constraint_animation(Object *ob); -protected: + void export_morph_animation(Object *ob); - void export_object_constraint_animation(Object *ob); + void write_bone_animation_matrix(Object *ob_arm, Bone *bone); - void export_morph_animation(Object *ob); + void write_bone_animation(Object *ob_arm, Bone *bone); - void write_bone_animation_matrix(Object *ob_arm, Bone *bone); + void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type); - void write_bone_animation(Object *ob_arm, Bone *bone); + void sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone); - void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type); + void sample_animation(float *v, + std::vector<float> &frames, + int type, + Bone *bone, + Object *ob_arm, + bPoseChannel *pChan); - void sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone); + void sample_animation(std::vector<float[4][4]> &mats, + std::vector<float> &frames, + Bone *bone, + Object *ob_arm, + bPoseChannel *pChan); - void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pChan); + // dae_bone_animation -> add_bone_animation + // (blend this into dae_bone_animation) + void dae_bone_animation(std::vector<float> &fra, + float *v, + int tm_type, + int axis, + std::string ob_name, + std::string bone_name); - void sample_animation(std::vector<float[4][4]> &mats, std::vector<float> &frames, Bone *bone, Object *ob_arm, bPoseChannel *pChan); + void dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone); - // dae_bone_animation -> add_bone_animation - // (blend this into dae_bone_animation) - void dae_bone_animation(std::vector<float> &fra, float *v, int tm_type, int axis, std::string ob_name, std::string bone_name); + void dae_baked_object_animation(std::vector<float> &fra, Object *ob); - void dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone); + float convert_time(float frame); - void dae_baked_object_animation(std::vector<float> &fra, Object *ob); + float convert_angle(float angle); - float convert_time(float frame); + std::vector<std::vector<std::string>> anim_meta; - float convert_angle(float angle); + /* Main entry point into Animation export (called for each exported object) */ + void exportAnimation(Object *ob, BCAnimationSampler &sampler); - std::vector<std::vector<std::string>> anim_meta; + /* export animation as separate trans/rot/scale curves */ + void export_curve_animation_set(Object *ob, BCAnimationSampler &sampler, bool export_tm_curves); - /* Main entry point into Animation export (called for each exported object) */ - void exportAnimation(Object *ob, BCAnimationSampler &sampler); + /* export one single curve */ + void export_curve_animation(Object *ob, BCAnimationCurve &curve); - /* export animation as separate trans/rot/scale curves */ - void export_curve_animation_set( - Object *ob, - BCAnimationSampler &sampler, - bool export_tm_curves); + /* export animation as matrix data */ + void export_matrix_animation(Object *ob, BCAnimationSampler &sampler); - /* export one single curve */ - void export_curve_animation( - Object *ob, - BCAnimationCurve &curve); + /* step through the bone hierarchy */ + void export_bone_animations_recursive(Object *ob_arm, Bone *bone, BCAnimationSampler &sampler); - /* export animation as matrix data */ - void export_matrix_animation( - Object *ob, - BCAnimationSampler &sampler); + /* Export for one bone */ + void export_bone_animation(Object *ob, Bone *bone, BCFrames &frames, BCMatrixSampleMap &outmats); - /* step through the bone hierarchy */ - void export_bone_animations_recursive( - Object *ob_arm, - Bone *bone, - BCAnimationSampler &sampler); + /* call to the low level collada exporter */ + void export_collada_curve_animation(std::string id, + std::string name, + std::string target, + std::string axis, + BCAnimationCurve &curve); - /* Export for one bone */ - void export_bone_animation( - Object *ob, - Bone *bone, - BCFrames &frames, - BCMatrixSampleMap &outmats); + /* call to the low level collada exporter */ + void export_collada_matrix_animation(std::string id, + std::string name, + std::string target, + BCFrames &frames, + BCMatrixSampleMap &outmats); - /* call to the low level collada exporter */ - void export_collada_curve_animation( - std::string id, - std::string name, - std::string target, - std::string axis, - BCAnimationCurve &curve); + BCAnimationCurve *get_modified_export_curve(Object *ob, + BCAnimationCurve &curve, + BCAnimationCurveMap &curves); - /* call to the low level collada exporter */ - void export_collada_matrix_animation( - std::string id, - std::string name, - std::string target, - BCFrames &frames, - BCMatrixSampleMap &outmats); + /* Helper functions */ + void openAnimationWithClip(std::string id, std::string name); + bool open_animation_container(bool has_container, Object *ob); + void close_animation_container(bool has_container); - BCAnimationCurve *get_modified_export_curve(Object *ob, BCAnimationCurve &curve, BCAnimationCurveMap &curves); + /* Input and Output sources (single valued) */ + std::string collada_source_from_values(BC_animation_source_type tm_channel, + COLLADASW::InputSemantic::Semantics semantic, + std::vector<float> &values, + const std::string &anim_id, + const std::string axis_name); - /* Helper functions */ - void openAnimationWithClip(std::string id, std::string name); - bool open_animation_container(bool has_container, Object *ob); - void close_animation_container(bool has_container); + /* Output sources (matrix data) */ + std::string collada_source_from_values(BCMatrixSampleMap &samples, const std::string &anim_id); - /* Input and Output sources (single valued) */ - std::string collada_source_from_values( - BC_animation_source_type tm_channel, - COLLADASW::InputSemantic::Semantics semantic, - std::vector<float> &values, - const std::string& anim_id, - const std::string axis_name); + /* Interpolation sources */ + std::string collada_linear_interpolation_source(int tot, const std::string &anim_id); - /* Output sources (matrix data) */ - std::string collada_source_from_values( - BCMatrixSampleMap &samples, - const std::string& anim_id); + /* source ID = animation_name + semantic_suffix */ - /* Interpolation sources */ - std::string collada_linear_interpolation_source( - int tot, - const std::string& anim_id); + std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic); - /* source ID = animation_name + semantic_suffix */ + void add_source_parameters(COLLADASW::SourceBase::ParameterNameList ¶m, + COLLADASW::InputSemantic::Semantics semantic, + bool is_rot, + const std::string axis, + bool transform); - std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic); + int get_point_in_curve(BCBezTriple &bezt, + COLLADASW::InputSemantic::Semantics semantic, + bool is_angle, + float *values); + int get_point_in_curve(const BCAnimationCurve &curve, + float sample_frame, + COLLADASW::InputSemantic::Semantics semantic, + bool is_angle, + float *values); - void add_source_parameters( - COLLADASW::SourceBase::ParameterNameList& param, - COLLADASW::InputSemantic::Semantics semantic, - bool is_rot, - const std::string axis, - bool transform); + std::string collada_tangent_from_curve(COLLADASW::InputSemantic::Semantics semantic, + BCAnimationCurve &curve, + const std::string &anim_id, + const std::string axis_name); - int get_point_in_curve(BCBezTriple &bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values); - int get_point_in_curve(const BCAnimationCurve &curve, float sample_frame, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values); - - std::string collada_tangent_from_curve( - COLLADASW::InputSemantic::Semantics semantic, - BCAnimationCurve &curve, - const std::string& anim_id, - const std::string axis_name); - - std::string collada_interpolation_source(const BCAnimationCurve &curve, const std::string& anim_id, std::string axis_name, bool *has_tangents); - - std::string get_axis_name(std::string channel, int id); - const std::string get_collada_name(std::string channel_target) const; - std::string get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name); - - /* ===================================== */ - /* Currently unused or not (yet?) needed */ - /* ===================================== */ - - bool is_bone_deform_group(Bone * bone); + std::string collada_interpolation_source(const BCAnimationCurve &curve, + const std::string &anim_id, + std::string axis_name, + bool *has_tangents); + + std::string get_axis_name(std::string channel, int id); + const std::string get_collada_name(std::string channel_target) const; + std::string get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name); + + /* ===================================== */ + /* Currently unused or not (yet?) needed */ + /* ===================================== */ + + bool is_bone_deform_group(Bone *bone); #if 0 - BC_animation_transform_type _get_transform_type(const std::string path); - void get_eul_source_for_quat(std::vector<float> &cache, Object *ob); + BC_animation_transform_type _get_transform_type(const std::string path); + void get_eul_source_for_quat(std::vector<float> &cache, Object *ob); #endif #ifdef WITH_MORPH_ANIMATION - void export_morph_animation( - Object *ob, - BCAnimationSampler &sampler); + void export_morph_animation(Object *ob, BCAnimationSampler &sampler); #endif - }; #endif diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 822e02ad9a3..f6695db1d0a 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -49,265 +49,278 @@ #include <algorithm> // first try node name, if not available (since is optional), fall back to original id -template<class T> -static const char *bc_get_joint_name(T *node) +template<class T> static const char *bc_get_joint_name(T *node) { - const std::string& id = node->getName(); - return id.size() ? id.c_str() : node->getOriginalId().c_str(); + const std::string &id = node->getName(); + return id.size() ? id.c_str() : node->getOriginalId().c_str(); } FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path) { - FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve"); - fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED); - fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); - fcu->array_index = array_index; - return fcu; + FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve"); + fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED); + fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); + fcu->array_index = array_index; + return fcu; } -void AnimationImporter::add_bezt(FCurve *fcu, float frame, float value, eBezTriple_Interpolation ipo) +void AnimationImporter::add_bezt(FCurve *fcu, + float frame, + float value, + eBezTriple_Interpolation ipo) { - //float fps = (float)FPS; - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - bez.vec[1][0] = frame; - bez.vec[1][1] = value; - bez.ipo = ipo; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); - calchandles_fcurve(fcu); + //float fps = (float)FPS; + BezTriple bez; + memset(&bez, 0, sizeof(BezTriple)); + bez.vec[1][0] = frame; + bez.vec[1][1] = value; + bez.ipo = ipo; /* use default interpolation mode here... */ + bez.f1 = bez.f2 = bez.f3 = SELECT; + bez.h1 = bez.h2 = HD_AUTO; + insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); + calchandles_fcurve(fcu); } // create one or several fcurves depending on the number of parameters being animated void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) { - COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues(); - COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues(); - - float fps = (float)FPS; - size_t dim = curve->getOutDimension(); - unsigned int i; - - std::vector<FCurve *>& fcurves = curve_map[curve->getUniqueId()]; - - switch (dim) { - case 1: // X, Y, Z or angle - case 3: // XYZ - case 4: - case 16: // matrix - { - for (i = 0; i < dim; i++) { - FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve"); - - fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED); - fcu->array_index = 0; - fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; - - for (unsigned int j = 0; j < curve->getKeyCount(); j++) { - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - - - // input, output - bez.vec[1][0] = bc_get_float_value(input, j) * fps; - bez.vec[1][1] = bc_get_float_value(output, j * dim + i); - bez.h1 = bez.h2 = HD_AUTO; - - if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER || - curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_STEP) - { - COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues(); - COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues(); - - // intangent - bez.vec[0][0] = bc_get_float_value(intan, (j * 2 * dim) + (2 * i)) * fps; - bez.vec[0][1] = bc_get_float_value(intan, (j * 2 * dim) + (2 * i) + 1); - - // outtangent - bez.vec[2][0] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i)) * fps; - bez.vec[2][1] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i) + 1); - if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER) { - bez.ipo = BEZT_IPO_BEZ; - bez.h1 = bez.h2 = HD_AUTO_ANIM; - } - else { - bez.ipo = BEZT_IPO_CONST; - } - } - else { - bez.ipo = BEZT_IPO_LIN; - } - // bez.ipo = U.ipo_new; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - - insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); - } - - calchandles_fcurve(fcu); - - fcurves.push_back(fcu); - unused_curves.push_back(fcu); - } - } - break; - default: - fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", (int)dim, curve->getOriginalId().c_str()); - } + COLLADAFW::FloatOrDoubleArray &input = curve->getInputValues(); + COLLADAFW::FloatOrDoubleArray &output = curve->getOutputValues(); + + float fps = (float)FPS; + size_t dim = curve->getOutDimension(); + unsigned int i; + + std::vector<FCurve *> &fcurves = curve_map[curve->getUniqueId()]; + + switch (dim) { + case 1: // X, Y, Z or angle + case 3: // XYZ + case 4: + case 16: // matrix + { + for (i = 0; i < dim; i++) { + FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve"); + + fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED); + fcu->array_index = 0; + fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; + + for (unsigned int j = 0; j < curve->getKeyCount(); j++) { + BezTriple bez; + memset(&bez, 0, sizeof(BezTriple)); + + // input, output + bez.vec[1][0] = bc_get_float_value(input, j) * fps; + bez.vec[1][1] = bc_get_float_value(output, j * dim + i); + bez.h1 = bez.h2 = HD_AUTO; + + if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER || + curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_STEP) { + COLLADAFW::FloatOrDoubleArray &intan = curve->getInTangentValues(); + COLLADAFW::FloatOrDoubleArray &outtan = curve->getOutTangentValues(); + + // intangent + bez.vec[0][0] = bc_get_float_value(intan, (j * 2 * dim) + (2 * i)) * fps; + bez.vec[0][1] = bc_get_float_value(intan, (j * 2 * dim) + (2 * i) + 1); + + // outtangent + bez.vec[2][0] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i)) * fps; + bez.vec[2][1] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i) + 1); + if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER) { + bez.ipo = BEZT_IPO_BEZ; + bez.h1 = bez.h2 = HD_AUTO_ANIM; + } + else { + bez.ipo = BEZT_IPO_CONST; + } + } + else { + bez.ipo = BEZT_IPO_LIN; + } + // bez.ipo = U.ipo_new; /* use default interpolation mode here... */ + bez.f1 = bez.f2 = bez.f3 = SELECT; + + insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); + } + + calchandles_fcurve(fcu); + + fcurves.push_back(fcu); + unused_curves.push_back(fcu); + } + } break; + default: + fprintf(stderr, + "Output dimension of %d is not yet supported (animation id = %s)\n", + (int)dim, + curve->getOriginalId().c_str()); + } } - void AnimationImporter::fcurve_deg_to_rad(FCurve *cu) { - for (unsigned int i = 0; i < cu->totvert; i++) { - // TODO convert handles too - cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f); - cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f); - cu->bezt[i].vec[2][1] *= DEG2RADF(1.0f); - } + for (unsigned int i = 0; i < cu->totvert; i++) { + // TODO convert handles too + cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f); + cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f); + cu->bezt[i].vec[2][1] *= DEG2RADF(1.0f); + } } void AnimationImporter::fcurve_is_used(FCurve *fcu) { - unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end()); + unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), + unused_curves.end()); } - -void AnimationImporter::add_fcurves_to_object(Main *bmain, Object *ob, std::vector<FCurve *>& curves, char *rna_path, int array_index, Animation *animated) +void AnimationImporter::add_fcurves_to_object(Main *bmain, + Object *ob, + std::vector<FCurve *> &curves, + char *rna_path, + int array_index, + Animation *animated) { - bAction *act; + bAction *act; - if (!ob->adt || !ob->adt->action) act = verify_adt_action(bmain, (ID *)&ob->id, 1); - else act = ob->adt->action; + if (!ob->adt || !ob->adt->action) + act = verify_adt_action(bmain, (ID *)&ob->id, 1); + else + act = ob->adt->action; - std::vector<FCurve *>::iterator it; - int i; + std::vector<FCurve *>::iterator it; + int i; #if 0 - char *p = strstr(rna_path, "rotation_euler"); - bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0'; + char *p = strstr(rna_path, "rotation_euler"); + bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0'; - // convert degrees to radians for rotation - if (is_rotation) - fcurve_deg_to_rad(fcu); + // convert degrees to radians for rotation + if (is_rotation) + fcurve_deg_to_rad(fcu); #endif - for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) { - FCurve *fcu = *it; - fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); - - if (array_index == -1) fcu->array_index = i; - else fcu->array_index = array_index; - - if (ob->type == OB_ARMATURE) { - bActionGroup *grp = NULL; - const char *bone_name = bc_get_joint_name(animated->node); - - if (bone_name) { - /* try to find group */ - grp = BKE_action_group_find_name(act, bone_name); - - /* no matching groups, so add one */ - if (grp == NULL) { - /* Add a new group, and make it active */ - grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup"); - - grp->flag = AGRP_SELECTED; - BLI_strncpy(grp->name, bone_name, sizeof(grp->name)); - - BLI_addtail(&act->groups, grp); - BLI_uniquename(&act->groups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.', - offsetof(bActionGroup, name), 64); - } - - /* add F-Curve to group */ - action_groups_add_channel(act, grp, fcu); - fcurve_is_used(fcu); - - } + for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) { + FCurve *fcu = *it; + fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); + + if (array_index == -1) + fcu->array_index = i; + else + fcu->array_index = array_index; + + if (ob->type == OB_ARMATURE) { + bActionGroup *grp = NULL; + const char *bone_name = bc_get_joint_name(animated->node); + + if (bone_name) { + /* try to find group */ + grp = BKE_action_group_find_name(act, bone_name); + + /* no matching groups, so add one */ + if (grp == NULL) { + /* Add a new group, and make it active */ + grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup"); + + grp->flag = AGRP_SELECTED; + BLI_strncpy(grp->name, bone_name, sizeof(grp->name)); + + BLI_addtail(&act->groups, grp); + BLI_uniquename(&act->groups, + grp, + CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), + '.', + offsetof(bActionGroup, name), + 64); + } + + /* add F-Curve to group */ + action_groups_add_channel(act, grp, fcu); + fcurve_is_used(fcu); + } #if 0 - if (is_rotation) { - fcurves_actionGroup_map[grp].push_back(fcu); - } + if (is_rotation) { + fcurves_actionGroup_map[grp].push_back(fcu); + } #endif - } - else { - BLI_addtail(&act->curves, fcu); - fcurve_is_used(fcu); - } - } + } + else { + BLI_addtail(&act->curves, fcu); + fcurve_is_used(fcu); + } + } } AnimationImporter::~AnimationImporter() { - // free unused FCurves - for (std::vector<FCurve *>::iterator it = unused_curves.begin(); it != unused_curves.end(); it++) - free_fcurve(*it); + // free unused FCurves + for (std::vector<FCurve *>::iterator it = unused_curves.begin(); it != unused_curves.end(); it++) + free_fcurve(*it); - if (unused_curves.size()) - fprintf(stderr, "removed %d unused curves\n", (int)unused_curves.size()); + if (unused_curves.size()) + fprintf(stderr, "removed %d unused curves\n", (int)unused_curves.size()); } bool AnimationImporter::write_animation(const COLLADAFW::Animation *anim) { - if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) { - COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve *)anim; - - // XXX Don't know if it's necessary - // Should we check outPhysicalDimension? - if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) { - fprintf(stderr, "Inputs physical dimension is not time.\n"); - return true; - } - - // a curve can have mixed interpolation type, - // in this case curve->getInterpolationTypes returns a list of interpolation types per key - COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType(); - - if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) { - switch (interp) { - case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR: - case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER: - case COLLADAFW::AnimationCurve::INTERPOLATION_STEP: - animation_to_fcurves(curve); - break; - default: - // TODO there're also CARDINAL, HERMITE, BSPLINE and STEP types - fprintf(stderr, "CARDINAL, HERMITE and BSPLINE anim interpolation types not supported yet.\n"); - break; - } - } - else { - // not supported yet - fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n"); - } - } - else { - fprintf(stderr, "FORMULA animation type is not supported yet.\n"); - } - - return true; + if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) { + COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve *)anim; + + // XXX Don't know if it's necessary + // Should we check outPhysicalDimension? + if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) { + fprintf(stderr, "Inputs physical dimension is not time.\n"); + return true; + } + + // a curve can have mixed interpolation type, + // in this case curve->getInterpolationTypes returns a list of interpolation types per key + COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType(); + + if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) { + switch (interp) { + case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR: + case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER: + case COLLADAFW::AnimationCurve::INTERPOLATION_STEP: + animation_to_fcurves(curve); + break; + default: + // TODO there're also CARDINAL, HERMITE, BSPLINE and STEP types + fprintf(stderr, + "CARDINAL, HERMITE and BSPLINE anim interpolation types not supported yet.\n"); + break; + } + } + else { + // not supported yet + fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n"); + } + } + else { + fprintf(stderr, "FORMULA animation type is not supported yet.\n"); + } + + return true; } // called on post-process stage after writeVisualScenes bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList *animlist) { - const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId(); - animlist_map[animlist_id] = animlist; + const COLLADAFW::UniqueId &animlist_id = animlist->getUniqueId(); + animlist_map[animlist_id] = animlist; #if 0 - // should not happen - if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) { - return true; - } - - // for bones rna_path is like: pose.bones["bone-name"].rotation + // should not happen + if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) { + return true; + } + // for bones rna_path is like: pose.bones["bone-name"].rotation #endif - return true; + return true; } // \todo refactor read_node_transform to not automatically apply anything, @@ -315,361 +328,379 @@ bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList *ani // necessary. Same for \ref get_node_mat void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob) { - float mat[4][4]; - TransformReader::get_node_mat(mat, node, &uid_animated_map, ob); - if (ob) { - copy_m4_m4(ob->obmat, mat); - BKE_object_apply_mat4(ob, ob->obmat, 0, 0); - } + float mat[4][4]; + TransformReader::get_node_mat(mat, node, &uid_animated_map, ob); + if (ob) { + copy_m4_m4(ob->obmat, mat); + BKE_object_apply_mat4(ob, ob->obmat, 0, 0); + } } #if 0 virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act) { - bActionGroup *grp; - int i; + bActionGroup *grp; + int i; - for (grp = (bActionGroup *)act->groups.first; grp; grp = grp->next) { + for (grp = (bActionGroup *)act->groups.first; grp; grp = grp->next) { - FCurve *eulcu[3] = {NULL, NULL, NULL}; + FCurve *eulcu[3] = {NULL, NULL, NULL}; - if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) - continue; + if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) + continue; - std::vector<FCurve *> &rot_fcurves = fcurves_actionGroup_map[grp]; + std::vector<FCurve *> &rot_fcurves = fcurves_actionGroup_map[grp]; - if (rot_fcurves.size() > 3) continue; + if (rot_fcurves.size() > 3) continue; - for (i = 0; i < rot_fcurves.size(); i++) - eulcu[rot_fcurves[i]->array_index] = rot_fcurves[i]; + for (i = 0; i < rot_fcurves.size(); i++) + eulcu[rot_fcurves[i]->array_index] = rot_fcurves[i]; - char joint_path[100]; - char rna_path[100]; + char joint_path[100]; + char rna_path[100]; - BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name); - BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path); + BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name); + BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path); - FCurve *quatcu[4] = { - create_fcurve(0, rna_path), - create_fcurve(1, rna_path), - create_fcurve(2, rna_path), - create_fcurve(3, rna_path) - }; + FCurve *quatcu[4] = { + create_fcurve(0, rna_path), + create_fcurve(1, rna_path), + create_fcurve(2, rna_path), + create_fcurve(3, rna_path) + }; - bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, grp->name); + bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, grp->name); - float m4[4][4], irest[3][3]; - invert_m4_m4(m4, chan->bone->arm_mat); - copy_m3_m4(irest, m4); + float m4[4][4], irest[3][3]; + invert_m4_m4(m4, chan->bone->arm_mat); + copy_m3_m4(irest, m4); - for (i = 0; i < 3; i++) { + for (i = 0; i < 3; i++) { - FCurve *cu = eulcu[i]; + FCurve *cu = eulcu[i]; - if (!cu) continue; + if (!cu) continue; - for (int j = 0; j < cu->totvert; j++) { - float frame = cu->bezt[j].vec[1][0]; + for (int j = 0; j < cu->totvert; j++) { + float frame = cu->bezt[j].vec[1][0]; - float eul[3] = { - eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f, - eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f, - eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f - }; + float eul[3] = { + eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f, + eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f, + eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f + }; - // make eul relative to bone rest pose - float rot[3][3], rel[3][3], quat[4]; + // make eul relative to bone rest pose + float rot[3][3], rel[3][3], quat[4]; - /*eul_to_mat3(rot, eul); + /*eul_to_mat3(rot, eul); - mul_m3_m3m3(rel, irest, rot); + mul_m3_m3m3(rel, irest, rot); - mat3_to_quat(quat, rel); - */ + mat3_to_quat(quat, rel); + */ - eul_to_quat(quat, eul); + eul_to_quat(quat, eul); - for (int k = 0; k < 4; k++) - create_bezt(quatcu[k], frame, quat[k], U.ipo_new); - } - } + for (int k = 0; k < 4; k++) + create_bezt(quatcu[k], frame, quat[k], U.ipo_new); + } + } - // now replace old Euler curves + // now replace old Euler curves - for (i = 0; i < 3; i++) { - if (!eulcu[i]) continue; + for (i = 0; i < 3; i++) { + if (!eulcu[i]) continue; - action_groups_remove_channel(act, eulcu[i]); - free_fcurve(eulcu[i]); - } + action_groups_remove_channel(act, eulcu[i]); + free_fcurve(eulcu[i]); + } - chan->rotmode = ROT_MODE_QUAT; + chan->rotmode = ROT_MODE_QUAT; - for (i = 0; i < 4; i++) - action_groups_add_channel(act, grp, quatcu[i]); - } + for (i = 0; i < 4; i++) + action_groups_add_channel(act, grp, quatcu[i]); + } - bPoseChannel *pchan; - for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { - pchan->rotmode = ROT_MODE_QUAT; - } + bPoseChannel *pchan; + for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + pchan->rotmode = ROT_MODE_QUAT; + } } #endif - //sets the rna_path and array index to curve -void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves, const char *rna_path, int array_index) +void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves, + const char *rna_path, + int array_index) { - std::vector<FCurve *>::iterator it; - int i; - for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) { - FCurve *fcu = *it; - fcu->rna_path = BLI_strdup(rna_path); - - if (array_index == -1) fcu->array_index = i; - else fcu->array_index = array_index; - - fcurve_is_used(fcu); - } + std::vector<FCurve *>::iterator it; + int i; + for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) { + FCurve *fcu = *it; + fcu->rna_path = BLI_strdup(rna_path); + + if (array_index == -1) + fcu->array_index = i; + else + fcu->array_index = array_index; + + fcurve_is_used(fcu); + } } void AnimationImporter::unused_fcurve(std::vector<FCurve *> *curves) { - // when an error happens and we can't actually use curve remove it from unused_curves - std::vector<FCurve *>::iterator it; - for (it = curves->begin(); it != curves->end(); it++) { - FCurve *fcu = *it; - fcurve_is_used(fcu); - } + // when an error happens and we can't actually use curve remove it from unused_curves + std::vector<FCurve *>::iterator it; + for (it = curves->begin(); it != curves->end(); it++) { + FCurve *fcu = *it; + fcurve_is_used(fcu); + } } void AnimationImporter::find_frames(std::vector<float> *frames, std::vector<FCurve *> *curves) { - std::vector<FCurve *>::iterator iter; - for (iter = curves->begin(); iter != curves->end(); iter++) { - FCurve *fcu = *iter; - - for (unsigned int k = 0; k < fcu->totvert; k++) { - //get frame value from bezTriple - float fra = fcu->bezt[k].vec[1][0]; - //if frame already not added add frame to frames - if (std::find(frames->begin(), frames->end(), fra) == frames->end()) - frames->push_back(fra); - - } - } + std::vector<FCurve *>::iterator iter; + for (iter = curves->begin(); iter != curves->end(); iter++) { + FCurve *fcu = *iter; + + for (unsigned int k = 0; k < fcu->totvert; k++) { + //get frame value from bezTriple + float fra = fcu->bezt[k].vec[1][0]; + //if frame already not added add frame to frames + if (std::find(frames->begin(), frames->end(), fra) == frames->end()) + frames->push_back(fra); + } + } } //creates the rna_paths and array indices of fcurves from animations using transformation and bound animation class of each animation. -void AnimationImporter:: Assign_transform_animations(COLLADAFW::Transformation *transform, - const COLLADAFW::AnimationList::AnimationBinding *binding, - std::vector<FCurve *> *curves, bool is_joint, char *joint_path) +void AnimationImporter::Assign_transform_animations( + COLLADAFW::Transformation *transform, + const COLLADAFW::AnimationList::AnimationBinding *binding, + std::vector<FCurve *> *curves, + bool is_joint, + char *joint_path) { - COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType(); - bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; - bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; - - //to check if the no of curves are valid - bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE || tm_type == COLLADAFW::Transformation::SCALE) && binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ); - - - if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) { - fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size()); - return; - } - - char rna_path[100]; - - switch (tm_type) { - case COLLADAFW::Transformation::TRANSLATE: - case COLLADAFW::Transformation::SCALE: - { - bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE; - if (is_joint) - BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale"); - else - BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path)); - - switch (binding->animationClass) { - case COLLADAFW::AnimationList::POSITION_X: - modify_fcurve(curves, rna_path, 0); - break; - case COLLADAFW::AnimationList::POSITION_Y: - modify_fcurve(curves, rna_path, 1); - break; - case COLLADAFW::AnimationList::POSITION_Z: - modify_fcurve(curves, rna_path, 2); - break; - case COLLADAFW::AnimationList::POSITION_XYZ: - modify_fcurve(curves, rna_path, -1); - break; - default: - unused_fcurve(curves); - fprintf(stderr, "AnimationClass %d is not supported for %s.\n", - binding->animationClass, loc ? "TRANSLATE" : "SCALE"); - } - break; - } - - - case COLLADAFW::Transformation::ROTATE: - { - if (is_joint) - BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path); - else - BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path)); - std::vector<FCurve *>::iterator iter; - for (iter = curves->begin(); iter != curves->end(); iter++) { - FCurve *fcu = *iter; - - //if transform is rotation the fcurves values must be turned in to radian. - if (is_rotation) - fcurve_deg_to_rad(fcu); - } - COLLADAFW::Rotate *rot = (COLLADAFW::Rotate *)transform; - COLLADABU::Math::Vector3& axis = rot->getRotationAxis(); - - switch (binding->animationClass) { - case COLLADAFW::AnimationList::ANGLE: - if (COLLADABU::Math::Vector3::UNIT_X == axis) { - modify_fcurve(curves, rna_path, 0); - } - else if (COLLADABU::Math::Vector3::UNIT_Y == axis) { - modify_fcurve(curves, rna_path, 1); - } - else if (COLLADABU::Math::Vector3::UNIT_Z == axis) { - modify_fcurve(curves, rna_path, 2); - } - else - unused_fcurve(curves); - break; - case COLLADAFW::AnimationList::AXISANGLE: - // TODO convert axis-angle to quat? or XYZ? - default: - unused_fcurve(curves); - fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n", - binding->animationClass); - } - break; - } - - case COLLADAFW::Transformation::MATRIX: + COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType(); + bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; + bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; + + //to check if the no of curves are valid + bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE || + tm_type == COLLADAFW::Transformation::SCALE) && + binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ); + + if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) { + fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size()); + return; + } + + char rna_path[100]; + + switch (tm_type) { + case COLLADAFW::Transformation::TRANSLATE: + case COLLADAFW::Transformation::SCALE: { + bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE; + if (is_joint) + BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale"); + else + BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path)); + + switch (binding->animationClass) { + case COLLADAFW::AnimationList::POSITION_X: + modify_fcurve(curves, rna_path, 0); + break; + case COLLADAFW::AnimationList::POSITION_Y: + modify_fcurve(curves, rna_path, 1); + break; + case COLLADAFW::AnimationList::POSITION_Z: + modify_fcurve(curves, rna_path, 2); + break; + case COLLADAFW::AnimationList::POSITION_XYZ: + modify_fcurve(curves, rna_path, -1); + break; + default: + unused_fcurve(curves); + fprintf(stderr, + "AnimationClass %d is not supported for %s.\n", + binding->animationClass, + loc ? "TRANSLATE" : "SCALE"); + } + break; + } + + case COLLADAFW::Transformation::ROTATE: { + if (is_joint) + BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path); + else + BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path)); + std::vector<FCurve *>::iterator iter; + for (iter = curves->begin(); iter != curves->end(); iter++) { + FCurve *fcu = *iter; + + //if transform is rotation the fcurves values must be turned in to radian. + if (is_rotation) + fcurve_deg_to_rad(fcu); + } + COLLADAFW::Rotate *rot = (COLLADAFW::Rotate *)transform; + COLLADABU::Math::Vector3 &axis = rot->getRotationAxis(); + + switch (binding->animationClass) { + case COLLADAFW::AnimationList::ANGLE: + if (COLLADABU::Math::Vector3::UNIT_X == axis) { + modify_fcurve(curves, rna_path, 0); + } + else if (COLLADABU::Math::Vector3::UNIT_Y == axis) { + modify_fcurve(curves, rna_path, 1); + } + else if (COLLADABU::Math::Vector3::UNIT_Z == axis) { + modify_fcurve(curves, rna_path, 2); + } + else + unused_fcurve(curves); + break; + case COLLADAFW::AnimationList::AXISANGLE: + // TODO convert axis-angle to quat? or XYZ? + default: + unused_fcurve(curves); + fprintf(stderr, + "AnimationClass %d is not supported for ROTATE transformation.\n", + binding->animationClass); + } + break; + } + + case COLLADAFW::Transformation::MATRIX: #if 0 - { - COLLADAFW::Matrix *mat = (COLLADAFW::Matrix*)transform; - COLLADABU::Math::Matrix4 mat4 = mat->getMatrix(); - switch (binding->animationClass) { - case COLLADAFW::AnimationList::TRANSFORM: - - } - } + { + COLLADAFW::Matrix *mat = (COLLADAFW::Matrix*)transform; + COLLADABU::Math::Matrix4 mat4 = mat->getMatrix(); + switch (binding->animationClass) { + case COLLADAFW::AnimationList::TRANSFORM: + + } + } #endif - unused_fcurve(curves); - break; - case COLLADAFW::Transformation::SKEW: - case COLLADAFW::Transformation::LOOKAT: - unused_fcurve(curves); - fprintf(stderr, "Animation of SKEW and LOOKAT transformations is not supported yet.\n"); - break; - } - + unused_fcurve(curves); + break; + case COLLADAFW::Transformation::SKEW: + case COLLADAFW::Transformation::LOOKAT: + unused_fcurve(curves); + fprintf(stderr, "Animation of SKEW and LOOKAT transformations is not supported yet.\n"); + break; + } } //creates the rna_paths and array indices of fcurves from animations using color and bound animation class of each animation. -void AnimationImporter:: Assign_color_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char *anim_type) +void AnimationImporter::Assign_color_animations(const COLLADAFW::UniqueId &listid, + ListBase *AnimCurves, + const char *anim_type) { - char rna_path[100]; - BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); - - const COLLADAFW::AnimationList *animlist = animlist_map[listid]; - if (animlist == NULL) - { - fprintf(stderr, "Collada: No animlist found for ID: %s of type %s\n", listid.toAscii().c_str(), anim_type); - return; - } - - const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); - //all the curves belonging to the current binding - std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { - animcurves = curve_map[bindings[j].animation]; - - switch (bindings[j].animationClass) { - case COLLADAFW::AnimationList::COLOR_R: - modify_fcurve(&animcurves, rna_path, 0); - break; - case COLLADAFW::AnimationList::COLOR_G: - modify_fcurve(&animcurves, rna_path, 1); - break; - case COLLADAFW::AnimationList::COLOR_B: - modify_fcurve(&animcurves, rna_path, 2); - break; - case COLLADAFW::AnimationList::COLOR_RGB: - case COLLADAFW::AnimationList::COLOR_RGBA: // to do-> set intensity - modify_fcurve(&animcurves, rna_path, -1); - break; - - default: - unused_fcurve(&animcurves); - fprintf(stderr, "AnimationClass %d is not supported for %s.\n", - bindings[j].animationClass, "COLOR"); - } - - std::vector<FCurve *>::iterator iter; - //Add the curves of the current animation to the object - for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { - FCurve *fcu = *iter; - BLI_addtail(AnimCurves, fcu); - fcurve_is_used(fcu); - } - } + char rna_path[100]; + BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); + + const COLLADAFW::AnimationList *animlist = animlist_map[listid]; + if (animlist == NULL) { + fprintf(stderr, + "Collada: No animlist found for ID: %s of type %s\n", + listid.toAscii().c_str(), + anim_type); + return; + } + + const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings(); + //all the curves belonging to the current binding + std::vector<FCurve *> animcurves; + for (unsigned int j = 0; j < bindings.getCount(); j++) { + animcurves = curve_map[bindings[j].animation]; + + switch (bindings[j].animationClass) { + case COLLADAFW::AnimationList::COLOR_R: + modify_fcurve(&animcurves, rna_path, 0); + break; + case COLLADAFW::AnimationList::COLOR_G: + modify_fcurve(&animcurves, rna_path, 1); + break; + case COLLADAFW::AnimationList::COLOR_B: + modify_fcurve(&animcurves, rna_path, 2); + break; + case COLLADAFW::AnimationList::COLOR_RGB: + case COLLADAFW::AnimationList::COLOR_RGBA: // to do-> set intensity + modify_fcurve(&animcurves, rna_path, -1); + break; + + default: + unused_fcurve(&animcurves); + fprintf(stderr, + "AnimationClass %d is not supported for %s.\n", + bindings[j].animationClass, + "COLOR"); + } + + std::vector<FCurve *>::iterator iter; + //Add the curves of the current animation to the object + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve *fcu = *iter; + BLI_addtail(AnimCurves, fcu); + fcurve_is_used(fcu); + } + } } -void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char *anim_type) +void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listid, + ListBase *AnimCurves, + const char *anim_type) { - char rna_path[100]; - if (animlist_map.find(listid) == animlist_map.end()) { - return; - } - else { - //anim_type has animations - const COLLADAFW::AnimationList *animlist = animlist_map[listid]; - const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); - //all the curves belonging to the current binding - std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { - animcurves = curve_map[bindings[j].animation]; - - BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); - modify_fcurve(&animcurves, rna_path, 0); - std::vector<FCurve *>::iterator iter; - //Add the curves of the current animation to the object - for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { - FCurve *fcu = *iter; - /* All anim_types whose values are to be converted from Degree to Radians can be ORed here */ - if (STREQ("spot_size", anim_type)) { - /* NOTE: Do NOT convert if imported file was made by blender <= 2.69.10 - * Reason: old blender versions stored spot_size in radians (was a bug) - */ - if (this->import_from_version == "" || BLI_natstrcmp(this->import_from_version.c_str(), "2.69.10") != -1) { - fcurve_deg_to_rad(fcu); - } - } - /** XXX What About animtype "rotation" ? */ - - BLI_addtail(AnimCurves, fcu); - fcurve_is_used(fcu); - } - } - } - + char rna_path[100]; + if (animlist_map.find(listid) == animlist_map.end()) { + return; + } + else { + //anim_type has animations + const COLLADAFW::AnimationList *animlist = animlist_map[listid]; + const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings(); + //all the curves belonging to the current binding + std::vector<FCurve *> animcurves; + for (unsigned int j = 0; j < bindings.getCount(); j++) { + animcurves = curve_map[bindings[j].animation]; + + BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); + modify_fcurve(&animcurves, rna_path, 0); + std::vector<FCurve *>::iterator iter; + //Add the curves of the current animation to the object + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve *fcu = *iter; + /* All anim_types whose values are to be converted from Degree to Radians can be ORed here */ + if (STREQ("spot_size", anim_type)) { + /* NOTE: Do NOT convert if imported file was made by blender <= 2.69.10 + * Reason: old blender versions stored spot_size in radians (was a bug) + */ + if (this->import_from_version == "" || + BLI_natstrcmp(this->import_from_version.c_str(), "2.69.10") != -1) { + fcurve_deg_to_rad(fcu); + } + } + /** XXX What About animtype "rotation" ? */ + + BLI_addtail(AnimCurves, fcu); + fcurve_is_used(fcu); + } + } + } } -float AnimationImporter::convert_to_focal_length(float in_xfov, int fov_type, float aspect, float sensorx) +float AnimationImporter::convert_to_focal_length(float in_xfov, + int fov_type, + float aspect, + float sensorx) { - // NOTE: Needs more testing (As we curretnly have no official test data for this) - float xfov = (fov_type == CAMERA_YFOV) ? (2.0f * atanf(aspect * tanf(DEG2RADF(in_xfov) * 0.5f))) : DEG2RADF(in_xfov); - return fov_to_focallength(xfov, sensorx); + // NOTE: Needs more testing (As we curretnly have no official test data for this) + float xfov = (fov_type == CAMERA_YFOV) ? + (2.0f * atanf(aspect * tanf(DEG2RADF(in_xfov) * 0.5f))) : + DEG2RADF(in_xfov); + return fov_to_focallength(xfov, sensorx); } /* @@ -677,182 +708,190 @@ float AnimationImporter::convert_to_focal_length(float in_xfov, int fov_type, fl * while blender internally uses focal length. * The imported animation curves must be converted appropriately. */ -void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const double aspect, Camera *cam, const char *anim_type, int fov_type) +void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId &listid, + ListBase *AnimCurves, + const double aspect, + Camera *cam, + const char *anim_type, + int fov_type) { - char rna_path[100]; - if (animlist_map.find(listid) == animlist_map.end()) { - return; - } - else { - //anim_type has animations - const COLLADAFW::AnimationList *animlist = animlist_map[listid]; - const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); - //all the curves belonging to the current binding - std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { - animcurves = curve_map[bindings[j].animation]; - - BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); - - modify_fcurve(&animcurves, rna_path, 0); - std::vector<FCurve *>::iterator iter; - //Add the curves of the current animation to the object - for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { - FCurve *fcu = *iter; - - for (unsigned int i = 0; i < fcu->totvert; i++) { - fcu->bezt[i].vec[0][1] = convert_to_focal_length(fcu->bezt[i].vec[0][1], fov_type, aspect, cam->sensor_x); - fcu->bezt[i].vec[1][1] = convert_to_focal_length(fcu->bezt[i].vec[1][1], fov_type, aspect, cam->sensor_x); - fcu->bezt[i].vec[2][1] = convert_to_focal_length(fcu->bezt[i].vec[2][1], fov_type, aspect, cam->sensor_x); - } - - BLI_addtail(AnimCurves, fcu); - fcurve_is_used(fcu); - } - } - } + char rna_path[100]; + if (animlist_map.find(listid) == animlist_map.end()) { + return; + } + else { + //anim_type has animations + const COLLADAFW::AnimationList *animlist = animlist_map[listid]; + const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings(); + //all the curves belonging to the current binding + std::vector<FCurve *> animcurves; + for (unsigned int j = 0; j < bindings.getCount(); j++) { + animcurves = curve_map[bindings[j].animation]; + + BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); + + modify_fcurve(&animcurves, rna_path, 0); + std::vector<FCurve *>::iterator iter; + //Add the curves of the current animation to the object + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve *fcu = *iter; + + for (unsigned int i = 0; i < fcu->totvert; i++) { + fcu->bezt[i].vec[0][1] = convert_to_focal_length( + fcu->bezt[i].vec[0][1], fov_type, aspect, cam->sensor_x); + fcu->bezt[i].vec[1][1] = convert_to_focal_length( + fcu->bezt[i].vec[1][1], fov_type, aspect, cam->sensor_x); + fcu->bezt[i].vec[2][1] = convert_to_focal_length( + fcu->bezt[i].vec[2][1], fov_type, aspect, cam->sensor_x); + } + + BLI_addtail(AnimCurves, fcu); + fcurve_is_used(fcu); + } + } + } } -void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, +void AnimationImporter::apply_matrix_curves(Object *ob, + std::vector<FCurve *> &animcurves, + COLLADAFW::Node *root, + COLLADAFW::Node *node, COLLADAFW::Transformation *tm) { - bool is_joint = node->getType() == COLLADAFW::Node::JOINT; - const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; - char joint_path[200]; - if (is_joint) - armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); - - std::vector<float> frames; - find_frames(&frames, &animcurves); - - float irest_dae[4][4]; - float rest[4][4], irest[4][4]; - - if (is_joint) { - get_joint_rest_mat(irest_dae, root, node); - invert_m4(irest_dae); - - Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name); - if (!bone) { - fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); - return; - } - - unit_m4(rest); - copy_m4_m4(rest, bone->arm_mat); - invert_m4_m4(irest, rest); - } - // new curves to assign matrix transform animation - FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale - unsigned int totcu = 10; - const char *tm_str = NULL; - char rna_path[200]; - for (int i = 0; i < totcu; i++) { - - int axis = i; - - if (i < 4) { - tm_str = "rotation_quaternion"; - axis = i; - } - else if (i < 7) { - tm_str = "location"; - axis = i - 4; - } - else { - tm_str = "scale"; - axis = i - 7; - } - - if (is_joint) - BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); - else - BLI_strncpy(rna_path, tm_str, sizeof(rna_path)); - newcu[i] = create_fcurve(axis, rna_path); - newcu[i]->totvert = frames.size(); - } - - if (frames.size() == 0) - return; - - std::sort(frames.begin(), frames.end()); - - std::vector<float>::iterator it; - - //float qref[4]; - //unit_qt(qref); - - // sample values at each frame - for (it = frames.begin(); it != frames.end(); it++) { - float fra = *it; - - float mat[4][4]; - float matfra[4][4]; - - unit_m4(matfra); - - // calc object-space mat - evaluate_transform_at_frame(matfra, node, fra); - - - // for joints, we need a special matrix - if (is_joint) { - // special matrix: iR * M * iR_dae * R - // where R, iR are bone rest and inverse rest mats in world space (Blender bones), - // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) - float temp[4][4], par[4][4]; - - // calc M - calc_joint_parent_mat_rest(par, NULL, root, node); - mul_m4_m4m4(temp, par, matfra); - - // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); - - // calc special matrix - mul_m4_series(mat, irest, temp, irest_dae, rest); - } - else { - copy_m4_m4(mat, matfra); - } - - float rot[4], loc[3], scale[3]; - mat4_decompose(loc, rot, scale, mat); - - // add keys - for (int i = 0; i < totcu; i++) { - if (i < 4) - add_bezt(newcu[i], fra, rot[i]); - else if (i < 7) - add_bezt(newcu[i], fra, loc[i - 4]); - else - add_bezt(newcu[i], fra, scale[i - 7]); - } - } - Main *bmain = CTX_data_main(mContext); - verify_adt_action(bmain, (ID *)&ob->id, 1); - - ListBase *curves = &ob->adt->action->curves; - - // add curves - for (int i = 0; i < totcu; i++) { - if (is_joint) - add_bone_fcurve(ob, node, newcu[i]); - else - BLI_addtail(curves, newcu[i]); - // fcurve_is_used(newcu[i]); // never added to unused - } - - - if (is_joint) { - bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name); - chan->rotmode = ROT_MODE_QUAT; - } - else { - ob->rotmode = ROT_MODE_QUAT; - } - - return; - + bool is_joint = node->getType() == COLLADAFW::Node::JOINT; + const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; + char joint_path[200]; + if (is_joint) + armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); + + std::vector<float> frames; + find_frames(&frames, &animcurves); + + float irest_dae[4][4]; + float rest[4][4], irest[4][4]; + + if (is_joint) { + get_joint_rest_mat(irest_dae, root, node); + invert_m4(irest_dae); + + Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name); + if (!bone) { + fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); + return; + } + + unit_m4(rest); + copy_m4_m4(rest, bone->arm_mat); + invert_m4_m4(irest, rest); + } + // new curves to assign matrix transform animation + FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale + unsigned int totcu = 10; + const char *tm_str = NULL; + char rna_path[200]; + for (int i = 0; i < totcu; i++) { + + int axis = i; + + if (i < 4) { + tm_str = "rotation_quaternion"; + axis = i; + } + else if (i < 7) { + tm_str = "location"; + axis = i - 4; + } + else { + tm_str = "scale"; + axis = i - 7; + } + + if (is_joint) + BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); + else + BLI_strncpy(rna_path, tm_str, sizeof(rna_path)); + newcu[i] = create_fcurve(axis, rna_path); + newcu[i]->totvert = frames.size(); + } + + if (frames.size() == 0) + return; + + std::sort(frames.begin(), frames.end()); + + std::vector<float>::iterator it; + + //float qref[4]; + //unit_qt(qref); + + // sample values at each frame + for (it = frames.begin(); it != frames.end(); it++) { + float fra = *it; + + float mat[4][4]; + float matfra[4][4]; + + unit_m4(matfra); + + // calc object-space mat + evaluate_transform_at_frame(matfra, node, fra); + + // for joints, we need a special matrix + if (is_joint) { + // special matrix: iR * M * iR_dae * R + // where R, iR are bone rest and inverse rest mats in world space (Blender bones), + // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) + float temp[4][4], par[4][4]; + + // calc M + calc_joint_parent_mat_rest(par, NULL, root, node); + mul_m4_m4m4(temp, par, matfra); + + // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); + + // calc special matrix + mul_m4_series(mat, irest, temp, irest_dae, rest); + } + else { + copy_m4_m4(mat, matfra); + } + + float rot[4], loc[3], scale[3]; + mat4_decompose(loc, rot, scale, mat); + + // add keys + for (int i = 0; i < totcu; i++) { + if (i < 4) + add_bezt(newcu[i], fra, rot[i]); + else if (i < 7) + add_bezt(newcu[i], fra, loc[i - 4]); + else + add_bezt(newcu[i], fra, scale[i - 7]); + } + } + Main *bmain = CTX_data_main(mContext); + verify_adt_action(bmain, (ID *)&ob->id, 1); + + ListBase *curves = &ob->adt->action->curves; + + // add curves + for (int i = 0; i < totcu; i++) { + if (is_joint) + add_bone_fcurve(ob, node, newcu[i]); + else + BLI_addtail(curves, newcu[i]); + // fcurve_is_used(newcu[i]); // never added to unused + } + + if (is_joint) { + bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name); + chan->rotmode = ROT_MODE_QUAT; + } + else { + ob->rotmode = ROT_MODE_QUAT; + } + + return; } /* @@ -867,1112 +906,1139 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a */ static const double get_aspect_ratio(const COLLADAFW::Camera *camera) { - double aspect = camera->getAspectRatio().getValue(); - - if (aspect == 0) { - const double yfov = camera->getYFov().getValue(); - - if (yfov == 0) { - aspect = 1; // assume yfov and xfov are equal - } - else { - const double xfov = camera->getXFov().getValue(); - if (xfov==0) - aspect = 1; - else - aspect = xfov / yfov; - } - } - return aspect; + double aspect = camera->getAspectRatio().getValue(); + + if (aspect == 0) { + const double yfov = camera->getYFov().getValue(); + + if (yfov == 0) { + aspect = 1; // assume yfov and xfov are equal + } + else { + const double xfov = camera->getXFov().getValue(); + if (xfov == 0) + aspect = 1; + else + aspect = xfov / yfov; + } + } + return aspect; } static ListBase &get_animation_curves(Main *bmain, Material *ma) { - bAction *act; - if (!ma->adt || !ma->adt->action) - act = verify_adt_action(bmain, (ID *)&ma->id, 1); - else - act = ma->adt->action; + bAction *act; + if (!ma->adt || !ma->adt->action) + act = verify_adt_action(bmain, (ID *)&ma->id, 1); + else + act = ma->adt->action; - return act->curves; + return act->curves; } -void AnimationImporter::translate_Animations(COLLADAFW::Node *node, - std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map, - std::multimap<COLLADAFW::UniqueId, Object *>& object_map, - std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map, - std::map<COLLADAFW::UniqueId, Material*> uid_material_map) +void AnimationImporter::translate_Animations( + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &root_map, + std::multimap<COLLADAFW::UniqueId, Object *> &object_map, + std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map, + std::map<COLLADAFW::UniqueId, Material *> uid_material_map) { - bool is_joint = node->getType() == COLLADAFW::Node::JOINT; - COLLADAFW::UniqueId uid = node->getUniqueId(); - COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid]; - - Object *ob; - if (is_joint) - ob = armature_importer->get_armature_for_joint(root); - else - ob = object_map.find(uid) == object_map.end() ? NULL : object_map.find(uid)->second; - - if (!ob) { - fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str()); - return; - } - - - AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map); - bAction *act; - Main *bmain = CTX_data_main(mContext); - - if ( (animType->transform) != 0) { - /* const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; */ /* UNUSED */ - char joint_path[200]; - - if (is_joint) - armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); - - if (!ob->adt || !ob->adt->action) - act = verify_adt_action(bmain, (ID *)&ob->id, 1); - - else - act = ob->adt->action; - - //Get the list of animation curves of the object - ListBase *AnimCurves = &(act->curves); - - const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations(); - - //for each transformation in node - for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) { - COLLADAFW::Transformation *transform = nodeTransforms[i]; - COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType(); - - bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; - bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; - - const COLLADAFW::UniqueId& listid = transform->getAnimationList(); - - //check if transformation has animations - if (animlist_map.find(listid) == animlist_map.end()) { - continue; - } - else { - //transformation has animations - const COLLADAFW::AnimationList *animlist = animlist_map[listid]; - const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); - //all the curves belonging to the current binding - std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { - animcurves = curve_map[bindings[j].animation]; - if (is_matrix) { - apply_matrix_curves(ob, animcurves, root, node, transform); - } - else { - if (is_joint) { - add_bone_animation_sampled(ob, animcurves, root, node, transform); - } - else { - //calculate rnapaths and array index of fcurves according to transformation and animation class - Assign_transform_animations(transform, &bindings[j], &animcurves, is_joint, joint_path); - - std::vector<FCurve *>::iterator iter; - //Add the curves of the current animation to the object - for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { - FCurve *fcu = *iter; - - BLI_addtail(AnimCurves, fcu); - fcurve_is_used(fcu); - } - } - - } - } - } - if (is_rotation && !is_joint) { - ob->rotmode = ROT_MODE_EUL; - } - } - } - - if ((animType->light) != 0) { - Light *lamp = (Light *) ob->data; - if (!lamp->adt || !lamp->adt->action) - act = verify_adt_action(bmain, (ID *)&lamp->id, 1); - else - act = lamp->adt->action; - - ListBase *AnimCurves = &(act->curves); - const COLLADAFW::InstanceLightPointerArray& nodeLights = node->getInstanceLights(); - - for (unsigned int i = 0; i < nodeLights.getCount(); i++) { - const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()]; - - if ((animType->light & LIGHT_COLOR) != 0) { - const COLLADAFW::Color *col = &(light->getColor()); - const COLLADAFW::UniqueId& listid = col->getAnimationList(); - - Assign_color_animations(listid, AnimCurves, "color"); - } - if ((animType->light & LIGHT_FOA) != 0) { - const COLLADAFW::AnimatableFloat *foa = &(light->getFallOffAngle()); - const COLLADAFW::UniqueId& listid = foa->getAnimationList(); - - Assign_float_animations(listid, AnimCurves, "spot_size"); - } - if ( (animType->light & LIGHT_FOE) != 0) { - const COLLADAFW::AnimatableFloat *foe = &(light->getFallOffExponent()); - const COLLADAFW::UniqueId& listid = foe->getAnimationList(); - - Assign_float_animations(listid, AnimCurves, "spot_blend"); - - } - } - } - - if (animType->camera != 0) { - - Camera *cam = (Camera *) ob->data; - if (!cam->adt || !cam->adt->action) - act = verify_adt_action(bmain, (ID *)&cam->id, 1); - else - act = cam->adt->action; - - ListBase *AnimCurves = &(act->curves); - const COLLADAFW::InstanceCameraPointerArray& nodeCameras = node->getInstanceCameras(); - - for (unsigned int i = 0; i < nodeCameras.getCount(); i++) { - const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()]; - - if ((animType->camera & CAMERA_XFOV) != 0) { - const COLLADAFW::AnimatableFloat *xfov = &(camera->getXFov()); - const COLLADAFW::UniqueId& listid = xfov->getAnimationList(); - double aspect = get_aspect_ratio(camera); - Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_XFOV); - } - - else if ((animType->camera & CAMERA_YFOV) != 0) { - const COLLADAFW::AnimatableFloat *yfov = &(camera->getYFov()); - const COLLADAFW::UniqueId& listid = yfov->getAnimationList(); - double aspect = get_aspect_ratio(camera); - Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_YFOV); - } - - else if ((animType->camera & CAMERA_XMAG) != 0) { - const COLLADAFW::AnimatableFloat *xmag = &(camera->getXMag()); - const COLLADAFW::UniqueId& listid = xmag->getAnimationList(); - Assign_float_animations(listid, AnimCurves, "ortho_scale"); - } - - else if ((animType->camera & CAMERA_YMAG) != 0) { - const COLLADAFW::AnimatableFloat *ymag = &(camera->getYMag()); - const COLLADAFW::UniqueId& listid = ymag->getAnimationList(); - Assign_float_animations(listid, AnimCurves, "ortho_scale"); - } - - if ((animType->camera & CAMERA_ZFAR) != 0) { - const COLLADAFW::AnimatableFloat *zfar = &(camera->getFarClippingPlane()); - const COLLADAFW::UniqueId& listid = zfar->getAnimationList(); - Assign_float_animations(listid, AnimCurves, "clip_end"); - } - - if ((animType->camera & CAMERA_ZNEAR) != 0) { - const COLLADAFW::AnimatableFloat *znear = &(camera->getNearClippingPlane()); - const COLLADAFW::UniqueId& listid = znear->getAnimationList(); - Assign_float_animations(listid, AnimCurves, "clip_start"); - } - - } - } - if (animType->material != 0) { - - Material *ma = give_current_material(ob, 1); - if (!ma->adt || !ma->adt->action) - act = verify_adt_action(bmain, (ID *)&ma->id, 1); - else - act = ma->adt->action; - - const COLLADAFW::InstanceGeometryPointerArray& nodeGeoms = node->getInstanceGeometries(); - for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) { - const COLLADAFW::MaterialBindingArray& matBinds = nodeGeoms[i]->getMaterialBindings(); - for (unsigned int j = 0; j < matBinds.getCount(); j++) { - const COLLADAFW::UniqueId & matuid = matBinds[j].getReferencedMaterial(); - const COLLADAFW::Effect *ef = (COLLADAFW::Effect *) (FW_object_map[matuid]); - if (ef != NULL) { /* can be NULL [#28909] */ - Material *ma = uid_material_map[matuid]; - if (!ma) { - fprintf(stderr, "Collada: Node %s refers to undefined material\n", node->getName().c_str()); - continue; - } - ListBase &AnimCurves = get_animation_curves(bmain, ma); - const COLLADAFW::CommonEffectPointerArray& commonEffects = ef->getCommonEffects(); - COLLADAFW::EffectCommon *efc = commonEffects[0]; - if ((animType->material & MATERIAL_SHININESS) != 0) { - const COLLADAFW::FloatOrParam *shin = &(efc->getShininess()); - const COLLADAFW::UniqueId& listid = shin->getAnimationList(); - Assign_float_animations(listid, &AnimCurves, "specular_hardness"); - } - - if ((animType->material & MATERIAL_IOR) != 0) { - const COLLADAFW::FloatOrParam *ior = &(efc->getIndexOfRefraction()); - const COLLADAFW::UniqueId& listid = ior->getAnimationList(); - Assign_float_animations(listid, &AnimCurves, "raytrace_transparency.ior"); - } - - if ((animType->material & MATERIAL_SPEC_COLOR) != 0) { - const COLLADAFW::ColorOrTexture *cot = &(efc->getSpecular()); - const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList(); - Assign_color_animations(listid, &AnimCurves, "specular_color"); - } - - if ((animType->material & MATERIAL_DIFF_COLOR) != 0) { - const COLLADAFW::ColorOrTexture *cot = &(efc->getDiffuse()); - const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList(); - Assign_color_animations(listid, &AnimCurves, "diffuse_color"); - } - } - } - } - } - - delete animType; + bool is_joint = node->getType() == COLLADAFW::Node::JOINT; + COLLADAFW::UniqueId uid = node->getUniqueId(); + COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid]; + + Object *ob; + if (is_joint) + ob = armature_importer->get_armature_for_joint(root); + else + ob = object_map.find(uid) == object_map.end() ? NULL : object_map.find(uid)->second; + + if (!ob) { + fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str()); + return; + } + + AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map); + bAction *act; + Main *bmain = CTX_data_main(mContext); + + if ((animType->transform) != 0) { + /* const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; */ /* UNUSED */ + char joint_path[200]; + + if (is_joint) + armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); + + if (!ob->adt || !ob->adt->action) + act = verify_adt_action(bmain, (ID *)&ob->id, 1); + + else + act = ob->adt->action; + + //Get the list of animation curves of the object + ListBase *AnimCurves = &(act->curves); + + const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations(); + + //for each transformation in node + for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) { + COLLADAFW::Transformation *transform = nodeTransforms[i]; + COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType(); + + bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; + bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; + + const COLLADAFW::UniqueId &listid = transform->getAnimationList(); + + //check if transformation has animations + if (animlist_map.find(listid) == animlist_map.end()) { + continue; + } + else { + //transformation has animations + const COLLADAFW::AnimationList *animlist = animlist_map[listid]; + const COLLADAFW::AnimationList::AnimationBindings &bindings = + animlist->getAnimationBindings(); + //all the curves belonging to the current binding + std::vector<FCurve *> animcurves; + for (unsigned int j = 0; j < bindings.getCount(); j++) { + animcurves = curve_map[bindings[j].animation]; + if (is_matrix) { + apply_matrix_curves(ob, animcurves, root, node, transform); + } + else { + if (is_joint) { + add_bone_animation_sampled(ob, animcurves, root, node, transform); + } + else { + //calculate rnapaths and array index of fcurves according to transformation and animation class + Assign_transform_animations( + transform, &bindings[j], &animcurves, is_joint, joint_path); + + std::vector<FCurve *>::iterator iter; + //Add the curves of the current animation to the object + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve *fcu = *iter; + + BLI_addtail(AnimCurves, fcu); + fcurve_is_used(fcu); + } + } + } + } + } + if (is_rotation && !is_joint) { + ob->rotmode = ROT_MODE_EUL; + } + } + } + + if ((animType->light) != 0) { + Light *lamp = (Light *)ob->data; + if (!lamp->adt || !lamp->adt->action) + act = verify_adt_action(bmain, (ID *)&lamp->id, 1); + else + act = lamp->adt->action; + + ListBase *AnimCurves = &(act->curves); + const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights(); + + for (unsigned int i = 0; i < nodeLights.getCount(); i++) { + const COLLADAFW::Light *light = (COLLADAFW::Light *) + FW_object_map[nodeLights[i]->getInstanciatedObjectId()]; + + if ((animType->light & LIGHT_COLOR) != 0) { + const COLLADAFW::Color *col = &(light->getColor()); + const COLLADAFW::UniqueId &listid = col->getAnimationList(); + + Assign_color_animations(listid, AnimCurves, "color"); + } + if ((animType->light & LIGHT_FOA) != 0) { + const COLLADAFW::AnimatableFloat *foa = &(light->getFallOffAngle()); + const COLLADAFW::UniqueId &listid = foa->getAnimationList(); + + Assign_float_animations(listid, AnimCurves, "spot_size"); + } + if ((animType->light & LIGHT_FOE) != 0) { + const COLLADAFW::AnimatableFloat *foe = &(light->getFallOffExponent()); + const COLLADAFW::UniqueId &listid = foe->getAnimationList(); + + Assign_float_animations(listid, AnimCurves, "spot_blend"); + } + } + } + + if (animType->camera != 0) { + + Camera *cam = (Camera *)ob->data; + if (!cam->adt || !cam->adt->action) + act = verify_adt_action(bmain, (ID *)&cam->id, 1); + else + act = cam->adt->action; + + ListBase *AnimCurves = &(act->curves); + const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras(); + + for (unsigned int i = 0; i < nodeCameras.getCount(); i++) { + const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) + FW_object_map[nodeCameras[i]->getInstanciatedObjectId()]; + + if ((animType->camera & CAMERA_XFOV) != 0) { + const COLLADAFW::AnimatableFloat *xfov = &(camera->getXFov()); + const COLLADAFW::UniqueId &listid = xfov->getAnimationList(); + double aspect = get_aspect_ratio(camera); + Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_XFOV); + } + + else if ((animType->camera & CAMERA_YFOV) != 0) { + const COLLADAFW::AnimatableFloat *yfov = &(camera->getYFov()); + const COLLADAFW::UniqueId &listid = yfov->getAnimationList(); + double aspect = get_aspect_ratio(camera); + Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_YFOV); + } + + else if ((animType->camera & CAMERA_XMAG) != 0) { + const COLLADAFW::AnimatableFloat *xmag = &(camera->getXMag()); + const COLLADAFW::UniqueId &listid = xmag->getAnimationList(); + Assign_float_animations(listid, AnimCurves, "ortho_scale"); + } + + else if ((animType->camera & CAMERA_YMAG) != 0) { + const COLLADAFW::AnimatableFloat *ymag = &(camera->getYMag()); + const COLLADAFW::UniqueId &listid = ymag->getAnimationList(); + Assign_float_animations(listid, AnimCurves, "ortho_scale"); + } + + if ((animType->camera & CAMERA_ZFAR) != 0) { + const COLLADAFW::AnimatableFloat *zfar = &(camera->getFarClippingPlane()); + const COLLADAFW::UniqueId &listid = zfar->getAnimationList(); + Assign_float_animations(listid, AnimCurves, "clip_end"); + } + + if ((animType->camera & CAMERA_ZNEAR) != 0) { + const COLLADAFW::AnimatableFloat *znear = &(camera->getNearClippingPlane()); + const COLLADAFW::UniqueId &listid = znear->getAnimationList(); + Assign_float_animations(listid, AnimCurves, "clip_start"); + } + } + } + if (animType->material != 0) { + + Material *ma = give_current_material(ob, 1); + if (!ma->adt || !ma->adt->action) + act = verify_adt_action(bmain, (ID *)&ma->id, 1); + else + act = ma->adt->action; + + const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries(); + for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) { + const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings(); + for (unsigned int j = 0; j < matBinds.getCount(); j++) { + const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial(); + const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]); + if (ef != NULL) { /* can be NULL [#28909] */ + Material *ma = uid_material_map[matuid]; + if (!ma) { + fprintf(stderr, + "Collada: Node %s refers to undefined material\n", + node->getName().c_str()); + continue; + } + ListBase &AnimCurves = get_animation_curves(bmain, ma); + const COLLADAFW::CommonEffectPointerArray &commonEffects = ef->getCommonEffects(); + COLLADAFW::EffectCommon *efc = commonEffects[0]; + if ((animType->material & MATERIAL_SHININESS) != 0) { + const COLLADAFW::FloatOrParam *shin = &(efc->getShininess()); + const COLLADAFW::UniqueId &listid = shin->getAnimationList(); + Assign_float_animations(listid, &AnimCurves, "specular_hardness"); + } + + if ((animType->material & MATERIAL_IOR) != 0) { + const COLLADAFW::FloatOrParam *ior = &(efc->getIndexOfRefraction()); + const COLLADAFW::UniqueId &listid = ior->getAnimationList(); + Assign_float_animations(listid, &AnimCurves, "raytrace_transparency.ior"); + } + + if ((animType->material & MATERIAL_SPEC_COLOR) != 0) { + const COLLADAFW::ColorOrTexture *cot = &(efc->getSpecular()); + const COLLADAFW::UniqueId &listid = cot->getColor().getAnimationList(); + Assign_color_animations(listid, &AnimCurves, "specular_color"); + } + + if ((animType->material & MATERIAL_DIFF_COLOR) != 0) { + const COLLADAFW::ColorOrTexture *cot = &(efc->getDiffuse()); + const COLLADAFW::UniqueId &listid = cot->getColor().getAnimationList(); + Assign_color_animations(listid, &AnimCurves, "diffuse_color"); + } + } + } + } + } + + delete animType; } -void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm) +void AnimationImporter::add_bone_animation_sampled(Object *ob, + std::vector<FCurve *> &animcurves, + COLLADAFW::Node *root, + COLLADAFW::Node *node, + COLLADAFW::Transformation *tm) { - const char *bone_name = bc_get_joint_name(node); - char joint_path[200]; - armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); - - std::vector<float> frames; - find_frames(&frames, &animcurves); - - // convert degrees to radians - if (tm->getTransformationType() == COLLADAFW::Transformation::ROTATE) { - - std::vector<FCurve *>::iterator iter; - for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { - FCurve *fcu = *iter; - - fcurve_deg_to_rad(fcu); - } - } - - - float irest_dae[4][4]; - float rest[4][4], irest[4][4]; - - get_joint_rest_mat(irest_dae, root, node); - invert_m4(irest_dae); - - Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name); - if (!bone) { - fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); - return; - } - - unit_m4(rest); - copy_m4_m4(rest, bone->arm_mat); - invert_m4_m4(irest, rest); - - // new curves to assign matrix transform animation - FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale - unsigned int totcu = 10; - const char *tm_str = NULL; - char rna_path[200]; - for (int i = 0; i < totcu; i++) { + const char *bone_name = bc_get_joint_name(node); + char joint_path[200]; + armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); - int axis = i; + std::vector<float> frames; + find_frames(&frames, &animcurves); - if (i < 4) { - tm_str = "rotation_quaternion"; - axis = i; - } - else if (i < 7) { - tm_str = "location"; - axis = i - 4; - } - else { - tm_str = "scale"; - axis = i - 7; - } + // convert degrees to radians + if (tm->getTransformationType() == COLLADAFW::Transformation::ROTATE) { + std::vector<FCurve *>::iterator iter; + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve *fcu = *iter; - BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); + fcurve_deg_to_rad(fcu); + } + } - newcu[i] = create_fcurve(axis, rna_path); - newcu[i]->totvert = frames.size(); - } + float irest_dae[4][4]; + float rest[4][4], irest[4][4]; - if (frames.size() == 0) - return; + get_joint_rest_mat(irest_dae, root, node); + invert_m4(irest_dae); + + Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name); + if (!bone) { + fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); + return; + } + + unit_m4(rest); + copy_m4_m4(rest, bone->arm_mat); + invert_m4_m4(irest, rest); + + // new curves to assign matrix transform animation + FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale + unsigned int totcu = 10; + const char *tm_str = NULL; + char rna_path[200]; + for (int i = 0; i < totcu; i++) { + + int axis = i; + + if (i < 4) { + tm_str = "rotation_quaternion"; + axis = i; + } + else if (i < 7) { + tm_str = "location"; + axis = i - 4; + } + else { + tm_str = "scale"; + axis = i - 7; + } + + BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); + + newcu[i] = create_fcurve(axis, rna_path); + newcu[i]->totvert = frames.size(); + } + + if (frames.size() == 0) + return; + + std::sort(frames.begin(), frames.end()); + + float qref[4]; + unit_qt(qref); + + std::vector<float>::iterator it; + + // sample values at each frame + for (it = frames.begin(); it != frames.end(); it++) { + float fra = *it; + + float mat[4][4]; + float matfra[4][4]; + + unit_m4(matfra); + + // calc object-space mat + evaluate_transform_at_frame(matfra, node, fra); + + // for joints, we need a special matrix + // special matrix: iR * M * iR_dae * R + // where R, iR are bone rest and inverse rest mats in world space (Blender bones), + // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) + float temp[4][4], par[4][4]; + + // calc M + calc_joint_parent_mat_rest(par, NULL, root, node); + mul_m4_m4m4(temp, par, matfra); + + // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); + + // calc special matrix + mul_m4_series(mat, irest, temp, irest_dae, rest); + + float rot[4], loc[3], scale[3]; + + bc_rotate_from_reference_quat(rot, qref, mat); + copy_qt_qt(qref, rot); - std::sort(frames.begin(), frames.end()); - - float qref[4]; - unit_qt(qref); - - std::vector<float>::iterator it; - - // sample values at each frame - for (it = frames.begin(); it != frames.end(); it++) { - float fra = *it; - - float mat[4][4]; - float matfra[4][4]; - - unit_m4(matfra); - - // calc object-space mat - evaluate_transform_at_frame(matfra, node, fra); - - - // for joints, we need a special matrix - // special matrix: iR * M * iR_dae * R - // where R, iR are bone rest and inverse rest mats in world space (Blender bones), - // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) - float temp[4][4], par[4][4]; - - - // calc M - calc_joint_parent_mat_rest(par, NULL, root, node); - mul_m4_m4m4(temp, par, matfra); - - // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); - - // calc special matrix - mul_m4_series(mat, irest, temp, irest_dae, rest); - - float rot[4], loc[3], scale[3]; - - bc_rotate_from_reference_quat(rot, qref, mat); - copy_qt_qt(qref, rot); - - copy_v3_v3(loc, mat[3]); - mat4_to_size(scale, mat); - - // add keys - for (int i = 0; i < totcu; i++) { - if (i < 4) - add_bezt(newcu[i], fra, rot[i]); - else if (i < 7) - add_bezt(newcu[i], fra, loc[i - 4]); - else - add_bezt(newcu[i], fra, scale[i - 7]); - } - } - Main *bmain = CTX_data_main(mContext); - verify_adt_action(bmain, (ID *)&ob->id, 1); - - // add curves - for (int i = 0; i < totcu; i++) { - add_bone_fcurve(ob, node, newcu[i]); - // fcurve_is_used(newcu[i]); // never added to unused - } - - bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name); - chan->rotmode = ROT_MODE_QUAT; + copy_v3_v3(loc, mat[3]); + mat4_to_size(scale, mat); + // add keys + for (int i = 0; i < totcu; i++) { + if (i < 4) + add_bezt(newcu[i], fra, rot[i]); + else if (i < 7) + add_bezt(newcu[i], fra, loc[i - 4]); + else + add_bezt(newcu[i], fra, scale[i - 7]); + } + } + Main *bmain = CTX_data_main(mContext); + verify_adt_action(bmain, (ID *)&ob->id, 1); + + // add curves + for (int i = 0; i < totcu; i++) { + add_bone_fcurve(ob, node, newcu[i]); + // fcurve_is_used(newcu[i]); // never added to unused + } + + bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name); + chan->rotmode = ROT_MODE_QUAT; } - //Check if object is animated by checking if animlist_map holds the animlist_id of node transforms -AnimationImporter::AnimMix *AnimationImporter::get_animation_type(const COLLADAFW::Node *node, - std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map) +AnimationImporter::AnimMix *AnimationImporter::get_animation_type( + const COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map) { - AnimMix *types = new AnimMix(); - - const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations(); - - //for each transformation in node - for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) { - COLLADAFW::Transformation *transform = nodeTransforms[i]; - const COLLADAFW::UniqueId& listid = transform->getAnimationList(); - - //check if transformation has animations - if (animlist_map.find(listid) == animlist_map.end()) { - continue; - } - else { - types->transform = types->transform | BC_NODE_TRANSFORM; - break; - } - } - const COLLADAFW::InstanceLightPointerArray& nodeLights = node->getInstanceLights(); - - for (unsigned int i = 0; i < nodeLights.getCount(); i++) { - const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()]; - types->light = setAnimType(&(light->getColor()), (types->light), LIGHT_COLOR); - types->light = setAnimType(&(light->getFallOffAngle()), (types->light), LIGHT_FOA); - types->light = setAnimType(&(light->getFallOffExponent()), (types->light), LIGHT_FOE); - - if (types->light != 0) break; - - } - - const COLLADAFW::InstanceCameraPointerArray& nodeCameras = node->getInstanceCameras(); - for (unsigned int i = 0; i < nodeCameras.getCount(); i++) { - const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()]; - if ( camera == NULL ) { - // Can happen if the node refers to an unknown camera. - continue; - } - - const bool is_perspective_type = camera->getCameraType() == COLLADAFW::Camera::PERSPECTIVE; - - int addition; - const COLLADAFW::Animatable *mag; - const COLLADAFW::UniqueId listid = camera->getYMag().getAnimationList(); - if (animlist_map.find(listid) != animlist_map.end()) { - mag = &(camera->getYMag()); - addition = (is_perspective_type) ? CAMERA_YFOV: CAMERA_YMAG; - } - else { - mag = &(camera->getXMag()); - addition = (is_perspective_type) ? CAMERA_XFOV: CAMERA_XMAG; - } - types->camera = setAnimType(mag, (types->camera), addition); - - types->camera = setAnimType(&(camera->getFarClippingPlane()), (types->camera), CAMERA_ZFAR); - types->camera = setAnimType(&(camera->getNearClippingPlane()), (types->camera), CAMERA_ZNEAR); - - if (types->camera != 0) break; - - } - - const COLLADAFW::InstanceGeometryPointerArray& nodeGeoms = node->getInstanceGeometries(); - for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) { - const COLLADAFW::MaterialBindingArray& matBinds = nodeGeoms[i]->getMaterialBindings(); - for (unsigned int j = 0; j < matBinds.getCount(); j++) { - const COLLADAFW::UniqueId & matuid = matBinds[j].getReferencedMaterial(); - const COLLADAFW::Effect *ef = (COLLADAFW::Effect *) (FW_object_map[matuid]); - if (ef != NULL) { /* can be NULL [#28909] */ - const COLLADAFW::CommonEffectPointerArray& commonEffects = ef->getCommonEffects(); - if (!commonEffects.empty()) { - COLLADAFW::EffectCommon *efc = commonEffects[0]; - types->material = setAnimType(&(efc->getShininess()), (types->material), MATERIAL_SHININESS); - types->material = setAnimType(&(efc->getSpecular().getColor()), (types->material), MATERIAL_SPEC_COLOR); - types->material = setAnimType(&(efc->getDiffuse().getColor()), (types->material), MATERIAL_DIFF_COLOR); - // types->material = setAnimType(&(efc->get()), (types->material), MATERIAL_TRANSPARENCY); - types->material = setAnimType(&(efc->getIndexOfRefraction()), (types->material), MATERIAL_IOR); - } - } - } - } - return types; + AnimMix *types = new AnimMix(); + + const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations(); + + //for each transformation in node + for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) { + COLLADAFW::Transformation *transform = nodeTransforms[i]; + const COLLADAFW::UniqueId &listid = transform->getAnimationList(); + + //check if transformation has animations + if (animlist_map.find(listid) == animlist_map.end()) { + continue; + } + else { + types->transform = types->transform | BC_NODE_TRANSFORM; + break; + } + } + const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights(); + + for (unsigned int i = 0; i < nodeLights.getCount(); i++) { + const COLLADAFW::Light *light = (COLLADAFW::Light *) + FW_object_map[nodeLights[i]->getInstanciatedObjectId()]; + types->light = setAnimType(&(light->getColor()), (types->light), LIGHT_COLOR); + types->light = setAnimType(&(light->getFallOffAngle()), (types->light), LIGHT_FOA); + types->light = setAnimType(&(light->getFallOffExponent()), (types->light), LIGHT_FOE); + + if (types->light != 0) + break; + } + + const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras(); + for (unsigned int i = 0; i < nodeCameras.getCount(); i++) { + const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) + FW_object_map[nodeCameras[i]->getInstanciatedObjectId()]; + if (camera == NULL) { + // Can happen if the node refers to an unknown camera. + continue; + } + + const bool is_perspective_type = camera->getCameraType() == COLLADAFW::Camera::PERSPECTIVE; + + int addition; + const COLLADAFW::Animatable *mag; + const COLLADAFW::UniqueId listid = camera->getYMag().getAnimationList(); + if (animlist_map.find(listid) != animlist_map.end()) { + mag = &(camera->getYMag()); + addition = (is_perspective_type) ? CAMERA_YFOV : CAMERA_YMAG; + } + else { + mag = &(camera->getXMag()); + addition = (is_perspective_type) ? CAMERA_XFOV : CAMERA_XMAG; + } + types->camera = setAnimType(mag, (types->camera), addition); + + types->camera = setAnimType(&(camera->getFarClippingPlane()), (types->camera), CAMERA_ZFAR); + types->camera = setAnimType(&(camera->getNearClippingPlane()), (types->camera), CAMERA_ZNEAR); + + if (types->camera != 0) + break; + } + + const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries(); + for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) { + const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings(); + for (unsigned int j = 0; j < matBinds.getCount(); j++) { + const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial(); + const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]); + if (ef != NULL) { /* can be NULL [#28909] */ + const COLLADAFW::CommonEffectPointerArray &commonEffects = ef->getCommonEffects(); + if (!commonEffects.empty()) { + COLLADAFW::EffectCommon *efc = commonEffects[0]; + types->material = setAnimType( + &(efc->getShininess()), (types->material), MATERIAL_SHININESS); + types->material = setAnimType( + &(efc->getSpecular().getColor()), (types->material), MATERIAL_SPEC_COLOR); + types->material = setAnimType( + &(efc->getDiffuse().getColor()), (types->material), MATERIAL_DIFF_COLOR); + // types->material = setAnimType(&(efc->get()), (types->material), MATERIAL_TRANSPARENCY); + types->material = setAnimType( + &(efc->getIndexOfRefraction()), (types->material), MATERIAL_IOR); + } + } + } + } + return types; } int AnimationImporter::setAnimType(const COLLADAFW::Animatable *prop, int types, int addition) { - int anim_type; - const COLLADAFW::UniqueId& listid = prop->getAnimationList(); - if (animlist_map.find(listid) != animlist_map.end()) - anim_type = types | addition; - else - anim_type = types; - - return anim_type; + int anim_type; + const COLLADAFW::UniqueId &listid = prop->getAnimationList(); + if (animlist_map.find(listid) != animlist_map.end()) + anim_type = types | addition; + else + anim_type = types; + + return anim_type; } // Is not used anymore. -void AnimationImporter::find_frames_old(std::vector<float> *frames, COLLADAFW::Node *node, COLLADAFW::Transformation::TransformationType tm_type) +void AnimationImporter::find_frames_old(std::vector<float> *frames, + COLLADAFW::Node *node, + COLLADAFW::Transformation::TransformationType tm_type) { - bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; - bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; - // for each <rotate>, <translate>, etc. there is a separate Transformation - const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations(); - - unsigned int i; - // find frames at which to sample plus convert all rotation keys to radians - for (i = 0; i < nodeTransforms.getCount(); i++) { - COLLADAFW::Transformation *transform = nodeTransforms[i]; - COLLADAFW::Transformation::TransformationType nodeTmType = transform->getTransformationType(); - - - if (nodeTmType == tm_type) { - //get animation bindings for the current transformation - const COLLADAFW::UniqueId& listid = transform->getAnimationList(); - //if transform is animated its animlist must exist. - if (animlist_map.find(listid) != animlist_map.end()) { - - const COLLADAFW::AnimationList *animlist = animlist_map[listid]; - const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); - - if (bindings.getCount()) { - //for each AnimationBinding get the fcurves which animate the transform - for (unsigned int j = 0; j < bindings.getCount(); j++) { - std::vector<FCurve *>& curves = curve_map[bindings[j].animation]; - bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE || nodeTmType == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ); - - if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) { - std::vector<FCurve *>::iterator iter; - - for (iter = curves.begin(); iter != curves.end(); iter++) { - FCurve *fcu = *iter; - - //if transform is rotation the fcurves values must be turned in to radian. - if (is_rotation) - fcurve_deg_to_rad(fcu); - - for (unsigned int k = 0; k < fcu->totvert; k++) { - //get frame value from bezTriple - float fra = fcu->bezt[k].vec[1][0]; - //if frame already not added add frame to frames - if (std::find(frames->begin(), frames->end(), fra) == frames->end()) - frames->push_back(fra); - } - } - } - else { - fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves.size()); - } - } - } - } - } - } + bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; + bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; + // for each <rotate>, <translate>, etc. there is a separate Transformation + const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations(); + + unsigned int i; + // find frames at which to sample plus convert all rotation keys to radians + for (i = 0; i < nodeTransforms.getCount(); i++) { + COLLADAFW::Transformation *transform = nodeTransforms[i]; + COLLADAFW::Transformation::TransformationType nodeTmType = transform->getTransformationType(); + + if (nodeTmType == tm_type) { + //get animation bindings for the current transformation + const COLLADAFW::UniqueId &listid = transform->getAnimationList(); + //if transform is animated its animlist must exist. + if (animlist_map.find(listid) != animlist_map.end()) { + + const COLLADAFW::AnimationList *animlist = animlist_map[listid]; + const COLLADAFW::AnimationList::AnimationBindings &bindings = + animlist->getAnimationBindings(); + + if (bindings.getCount()) { + //for each AnimationBinding get the fcurves which animate the transform + for (unsigned int j = 0; j < bindings.getCount(); j++) { + std::vector<FCurve *> &curves = curve_map[bindings[j].animation]; + bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE || + nodeTmType == COLLADAFW::Transformation::SCALE) && + bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ); + + if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) { + std::vector<FCurve *>::iterator iter; + + for (iter = curves.begin(); iter != curves.end(); iter++) { + FCurve *fcu = *iter; + + //if transform is rotation the fcurves values must be turned in to radian. + if (is_rotation) + fcurve_deg_to_rad(fcu); + + for (unsigned int k = 0; k < fcu->totvert; k++) { + //get frame value from bezTriple + float fra = fcu->bezt[k].vec[1][0]; + //if frame already not added add frame to frames + if (std::find(frames->begin(), frames->end(), fra) == frames->end()) + frames->push_back(fra); + } + } + } + else { + fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves.size()); + } + } + } + } + } + } } - - // prerequisites: // animlist_map - map animlist id -> animlist // curve_map - map anim id -> curve(s) -Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node, - std::map<COLLADAFW::UniqueId, Object *>& object_map, - std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map, - COLLADAFW::Transformation::TransformationType tm_type, - Object *par_job) +Object *AnimationImporter::translate_animation_OLD( + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Object *> &object_map, + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &root_map, + COLLADAFW::Transformation::TransformationType tm_type, + Object *par_job) { - bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; - bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; - bool is_joint = node->getType() == COLLADAFW::Node::JOINT; + bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; + bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; + bool is_joint = node->getType() == COLLADAFW::Node::JOINT; - COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()]; - Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()]; - const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; - if (!ob) { - fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str()); - return NULL; - } + COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? + node : + root_map[node->getUniqueId()]; + Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : + object_map[node->getUniqueId()]; + const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; + if (!ob) { + fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str()); + return NULL; + } - // frames at which to sample - std::vector<float> frames; + // frames at which to sample + std::vector<float> frames; - find_frames_old(&frames, node, tm_type); + find_frames_old(&frames, node, tm_type); - unsigned int i; + unsigned int i; - float irest_dae[4][4]; - float rest[4][4], irest[4][4]; + float irest_dae[4][4]; + float rest[4][4], irest[4][4]; - if (is_joint) { - get_joint_rest_mat(irest_dae, root, node); - invert_m4(irest_dae); + if (is_joint) { + get_joint_rest_mat(irest_dae, root, node); + invert_m4(irest_dae); - Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name); - if (!bone) { - fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); - return NULL; - } + Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name); + if (!bone) { + fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); + return NULL; + } - unit_m4(rest); - copy_m4_m4(rest, bone->arm_mat); - invert_m4_m4(irest, rest); - } + unit_m4(rest); + copy_m4_m4(rest, bone->arm_mat); + invert_m4_m4(irest, rest); + } - Object *job = NULL; + Object *job = NULL; #ifdef ARMATURE_TEST - FCurve *job_curves[10]; - job = get_joint_object(root, node, par_job); + FCurve *job_curves[10]; + job = get_joint_object(root, node, par_job); #endif - if (frames.size() == 0) - return job; - - std::sort(frames.begin(), frames.end()); - - const char *tm_str = NULL; - switch (tm_type) { - case COLLADAFW::Transformation::ROTATE: - tm_str = "rotation_quaternion"; - break; - case COLLADAFW::Transformation::SCALE: - tm_str = "scale"; - break; - case COLLADAFW::Transformation::TRANSLATE: - tm_str = "location"; - break; - case COLLADAFW::Transformation::MATRIX: - break; - default: - return job; - } - - char rna_path[200]; - char joint_path[200]; - - if (is_joint) - armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); - - // new curves - FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale - unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3); - - for (i = 0; i < totcu; i++) { - - int axis = i; - - if (is_matrix) { - if (i < 4) { - tm_str = "rotation_quaternion"; - axis = i; - } - else if (i < 7) { - tm_str = "location"; - axis = i - 4; - } - else { - tm_str = "scale"; - axis = i - 7; - } - } - - if (is_joint) - BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); - else - BLI_strncpy(rna_path, tm_str, sizeof(rna_path)); - newcu[i] = create_fcurve(axis, rna_path); + if (frames.size() == 0) + return job; + + std::sort(frames.begin(), frames.end()); + + const char *tm_str = NULL; + switch (tm_type) { + case COLLADAFW::Transformation::ROTATE: + tm_str = "rotation_quaternion"; + break; + case COLLADAFW::Transformation::SCALE: + tm_str = "scale"; + break; + case COLLADAFW::Transformation::TRANSLATE: + tm_str = "location"; + break; + case COLLADAFW::Transformation::MATRIX: + break; + default: + return job; + } + + char rna_path[200]; + char joint_path[200]; + + if (is_joint) + armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); + + // new curves + FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale + unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3); + + for (i = 0; i < totcu; i++) { + + int axis = i; + + if (is_matrix) { + if (i < 4) { + tm_str = "rotation_quaternion"; + axis = i; + } + else if (i < 7) { + tm_str = "location"; + axis = i - 4; + } + else { + tm_str = "scale"; + axis = i - 7; + } + } + + if (is_joint) + BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); + else + BLI_strncpy(rna_path, tm_str, sizeof(rna_path)); + newcu[i] = create_fcurve(axis, rna_path); #ifdef ARMATURE_TEST - if (is_joint) - job_curves[i] = create_fcurve(axis, tm_str); + if (is_joint) + job_curves[i] = create_fcurve(axis, tm_str); #endif - } - - std::vector<float>::iterator it; - - // sample values at each frame - for (it = frames.begin(); it != frames.end(); it++) { - float fra = *it; - - float mat[4][4]; - float matfra[4][4]; - - unit_m4(matfra); - - // calc object-space mat - evaluate_transform_at_frame(matfra, node, fra); - - // for joints, we need a special matrix - if (is_joint) { - // special matrix: iR * M * iR_dae * R - // where R, iR are bone rest and inverse rest mats in world space (Blender bones), - // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) - float temp[4][4], par[4][4]; - - // calc M - calc_joint_parent_mat_rest(par, NULL, root, node); - mul_m4_m4m4(temp, par, matfra); - - // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); - - // calc special matrix - mul_m4_series(mat, irest, temp, irest_dae, rest); - } - else { - copy_m4_m4(mat, matfra); - } - - float val[4] = {}; - float rot[4], loc[3], scale[3]; - - switch (tm_type) { - case COLLADAFW::Transformation::ROTATE: - mat4_to_quat(val, mat); - break; - case COLLADAFW::Transformation::SCALE: - mat4_to_size(val, mat); - break; - case COLLADAFW::Transformation::TRANSLATE: - copy_v3_v3(val, mat[3]); - break; - case COLLADAFW::Transformation::MATRIX: - mat4_to_quat(rot, mat); - copy_v3_v3(loc, mat[3]); - mat4_to_size(scale, mat); - break; - default: - break; - } - - // add keys - for (i = 0; i < totcu; i++) { - if (is_matrix) { - if (i < 4) - add_bezt(newcu[i], fra, rot[i]); - else if (i < 7) - add_bezt(newcu[i], fra, loc[i - 4]); - else - add_bezt(newcu[i], fra, scale[i - 7]); - } - else { - add_bezt(newcu[i], fra, val[i]); - } - } + } + + std::vector<float>::iterator it; + + // sample values at each frame + for (it = frames.begin(); it != frames.end(); it++) { + float fra = *it; + + float mat[4][4]; + float matfra[4][4]; + + unit_m4(matfra); + + // calc object-space mat + evaluate_transform_at_frame(matfra, node, fra); + + // for joints, we need a special matrix + if (is_joint) { + // special matrix: iR * M * iR_dae * R + // where R, iR are bone rest and inverse rest mats in world space (Blender bones), + // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) + float temp[4][4], par[4][4]; + + // calc M + calc_joint_parent_mat_rest(par, NULL, root, node); + mul_m4_m4m4(temp, par, matfra); + + // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); + + // calc special matrix + mul_m4_series(mat, irest, temp, irest_dae, rest); + } + else { + copy_m4_m4(mat, matfra); + } + + float val[4] = {}; + float rot[4], loc[3], scale[3]; + + switch (tm_type) { + case COLLADAFW::Transformation::ROTATE: + mat4_to_quat(val, mat); + break; + case COLLADAFW::Transformation::SCALE: + mat4_to_size(val, mat); + break; + case COLLADAFW::Transformation::TRANSLATE: + copy_v3_v3(val, mat[3]); + break; + case COLLADAFW::Transformation::MATRIX: + mat4_to_quat(rot, mat); + copy_v3_v3(loc, mat[3]); + mat4_to_size(scale, mat); + break; + default: + break; + } + + // add keys + for (i = 0; i < totcu; i++) { + if (is_matrix) { + if (i < 4) + add_bezt(newcu[i], fra, rot[i]); + else if (i < 7) + add_bezt(newcu[i], fra, loc[i - 4]); + else + add_bezt(newcu[i], fra, scale[i - 7]); + } + else { + add_bezt(newcu[i], fra, val[i]); + } + } #ifdef ARMATURE_TEST - if (is_joint) { - switch (tm_type) { - case COLLADAFW::Transformation::ROTATE: - mat4_to_quat(val, matfra); - break; - case COLLADAFW::Transformation::SCALE: - mat4_to_size(val, matfra); - break; - case COLLADAFW::Transformation::TRANSLATE: - copy_v3_v3(val, matfra[3]); - break; - case MATRIX: - mat4_to_quat(rot, matfra); - copy_v3_v3(loc, matfra[3]); - mat4_to_size(scale, matfra); - break; - default: - break; - } - - for (i = 0; i < totcu; i++) { - if (is_matrix) { - if (i < 4) - add_bezt(job_curves[i], fra, rot[i]); - else if (i < 7) - add_bezt(job_curves[i], fra, loc[i - 4]); - else - add_bezt(job_curves[i], fra, scale[i - 7]); - } - else { - add_bezt(job_curves[i], fra, val[i]); - } - } - } + if (is_joint) { + switch (tm_type) { + case COLLADAFW::Transformation::ROTATE: + mat4_to_quat(val, matfra); + break; + case COLLADAFW::Transformation::SCALE: + mat4_to_size(val, matfra); + break; + case COLLADAFW::Transformation::TRANSLATE: + copy_v3_v3(val, matfra[3]); + break; + case MATRIX: + mat4_to_quat(rot, matfra); + copy_v3_v3(loc, matfra[3]); + mat4_to_size(scale, matfra); + break; + default: + break; + } + + for (i = 0; i < totcu; i++) { + if (is_matrix) { + if (i < 4) + add_bezt(job_curves[i], fra, rot[i]); + else if (i < 7) + add_bezt(job_curves[i], fra, loc[i - 4]); + else + add_bezt(job_curves[i], fra, scale[i - 7]); + } + else { + add_bezt(job_curves[i], fra, val[i]); + } + } + } #endif - } - Main *bmain = CTX_data_main(mContext); - verify_adt_action(bmain, (ID *)&ob->id, 1); + } + Main *bmain = CTX_data_main(mContext); + verify_adt_action(bmain, (ID *)&ob->id, 1); - ListBase *curves = &ob->adt->action->curves; + ListBase *curves = &ob->adt->action->curves; - // add curves - for (i = 0; i < totcu; i++) { - if (is_joint) - add_bone_fcurve(ob, node, newcu[i]); - else - BLI_addtail(curves, newcu[i]); + // add curves + for (i = 0; i < totcu; i++) { + if (is_joint) + add_bone_fcurve(ob, node, newcu[i]); + else + BLI_addtail(curves, newcu[i]); #ifdef ARMATURE_TEST - if (is_joint) - BLI_addtail(&job->adt->action->curves, job_curves[i]); + if (is_joint) + BLI_addtail(&job->adt->action->curves, job_curves[i]); #endif - } - - if (is_rotation || is_matrix) { - if (is_joint) { - bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name); - chan->rotmode = ROT_MODE_QUAT; - } - else { - ob->rotmode = ROT_MODE_QUAT; - } - } - - return job; + } + + if (is_rotation || is_matrix) { + if (is_joint) { + bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name); + chan->rotmode = ROT_MODE_QUAT; + } + else { + ob->rotmode = ROT_MODE_QUAT; + } + } + + return job; } // internal, better make it private // warning: evaluates only rotation and only assigns matrix transforms now // prerequisites: animlist_map, curve_map -void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra) +void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], + COLLADAFW::Node *node, + float fra) { - const COLLADAFW::TransformationPointerArray& tms = node->getTransformations(); - - unit_m4(mat); - - for (unsigned int i = 0; i < tms.getCount(); i++) { - COLLADAFW::Transformation *tm = tms[i]; - COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); - float m[4][4]; - - unit_m4(m); - - std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); - if (!evaluate_animation(tm, m, fra, nodename.c_str())) { - switch (type) { - case COLLADAFW::Transformation::ROTATE: - dae_rotate_to_mat4(tm, m); - break; - case COLLADAFW::Transformation::TRANSLATE: - dae_translate_to_mat4(tm, m); - break; - case COLLADAFW::Transformation::SCALE: - dae_scale_to_mat4(tm, m); - break; - case COLLADAFW::Transformation::MATRIX: - dae_matrix_to_mat4(tm, m); - break; - default: - fprintf(stderr, "unsupported transformation type %d\n", type); - } - } - - float temp[4][4]; - copy_m4_m4(temp, mat); - - mul_m4_m4m4(mat, temp, m); - } + const COLLADAFW::TransformationPointerArray &tms = node->getTransformations(); + + unit_m4(mat); + + for (unsigned int i = 0; i < tms.getCount(); i++) { + COLLADAFW::Transformation *tm = tms[i]; + COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); + float m[4][4]; + + unit_m4(m); + + std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); + if (!evaluate_animation(tm, m, fra, nodename.c_str())) { + switch (type) { + case COLLADAFW::Transformation::ROTATE: + dae_rotate_to_mat4(tm, m); + break; + case COLLADAFW::Transformation::TRANSLATE: + dae_translate_to_mat4(tm, m); + break; + case COLLADAFW::Transformation::SCALE: + dae_scale_to_mat4(tm, m); + break; + case COLLADAFW::Transformation::MATRIX: + dae_matrix_to_mat4(tm, m); + break; + default: + fprintf(stderr, "unsupported transformation type %d\n", type); + } + } + + float temp[4][4]; + copy_m4_m4(temp, mat); + + mul_m4_m4m4(mat, temp, m); + } } static void report_class_type_unsupported(const char *path, - const COLLADAFW::AnimationList::AnimationClass animclass, - const COLLADAFW::Transformation::TransformationType type) + const COLLADAFW::AnimationList::AnimationClass animclass, + const COLLADAFW::Transformation::TransformationType type) { - if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) { - fprintf(stderr, "%s: UNKNOWN animation class\n", path); - } - else { - fprintf(stderr, "%s: animation class %d is not supported yet for transformation type %d\n", path, animclass, type); - } + if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) { + fprintf(stderr, "%s: UNKNOWN animation class\n", path); + } + else { + fprintf(stderr, + "%s: animation class %d is not supported yet for transformation type %d\n", + path, + animclass, + type); + } } // return true to indicate that mat contains a sane value -bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra, const char *node_id) +bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, + float mat[4][4], + float fra, + const char *node_id) { - const COLLADAFW::UniqueId& listid = tm->getAnimationList(); - COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); - - if (type != COLLADAFW::Transformation::ROTATE && - type != COLLADAFW::Transformation::SCALE && - type != COLLADAFW::Transformation::TRANSLATE && - type != COLLADAFW::Transformation::MATRIX) - { - fprintf(stderr, "animation of transformation %d is not supported yet\n", type); - return false; - } - - if (animlist_map.find(listid) == animlist_map.end()) - return false; - - const COLLADAFW::AnimationList *animlist = animlist_map[listid]; - const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); - - if (bindings.getCount()) { - float vec[3]; - - bool is_scale = (type == COLLADAFW::Transformation::SCALE); - bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE); - - if (is_scale) - dae_scale_to_v3(tm, vec); - else if (is_translate) - dae_translate_to_v3(tm, vec); - - for (unsigned int index = 0; index < bindings.getCount(); index++) { - const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[index]; - std::vector<FCurve *>& curves = curve_map[binding.animation]; - COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass; - char path[100]; - - switch (type) { - case COLLADAFW::Transformation::ROTATE: - BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, index); - break; - case COLLADAFW::Transformation::SCALE: - BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, index); - break; - case COLLADAFW::Transformation::TRANSLATE: - BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, index); - break; - case COLLADAFW::Transformation::MATRIX: - BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, index); - break; - default: - break; - } - - if (type == COLLADAFW::Transformation::ROTATE) { - if (curves.size() != 1) { - fprintf(stderr, "expected 1 curve, got %d\n", (int)curves.size()); - return false; - } - - // TODO support other animclasses - if (animclass != COLLADAFW::AnimationList::ANGLE) { - report_class_type_unsupported(path, animclass, type); - return false; - } - - COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate *)tm)->getRotationAxis(); - - float ax[3] = {(float)axis[0], (float)axis[1], (float)axis[2]}; - float angle = evaluate_fcurve(curves[0], fra); - axis_angle_to_mat4(mat, ax, angle); - - return true; - } - else if (is_scale || is_translate) { - bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ; - - if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) { - if (is_xyz) - fprintf(stderr, "%s: expected 3 curves, got %d\n", path, (int)curves.size()); - else - fprintf(stderr, "%s: expected 1 curve, got %d\n", path, (int)curves.size()); - return false; - } - - switch (animclass) { - case COLLADAFW::AnimationList::POSITION_X: - vec[0] = evaluate_fcurve(curves[0], fra); - break; - case COLLADAFW::AnimationList::POSITION_Y: - vec[1] = evaluate_fcurve(curves[0], fra); - break; - case COLLADAFW::AnimationList::POSITION_Z: - vec[2] = evaluate_fcurve(curves[0], fra); - break; - case COLLADAFW::AnimationList::POSITION_XYZ: - vec[0] = evaluate_fcurve(curves[0], fra); - vec[1] = evaluate_fcurve(curves[1], fra); - vec[2] = evaluate_fcurve(curves[2], fra); - break; - default: - report_class_type_unsupported(path, animclass, type); - break; - } - } - else if (type == COLLADAFW::Transformation::MATRIX) { - // for now, of matrix animation, support only the case when all values are packed into one animation - if (curves.size() != 16) { - fprintf(stderr, "%s: expected 16 curves, got %d\n", path, (int)curves.size()); - return false; - } - - COLLADABU::Math::Matrix4 matrix; - int mi = 0, mj = 0; - - for (std::vector<FCurve *>::iterator it = curves.begin(); it != curves.end(); it++) { - matrix.setElement(mi, mj, evaluate_fcurve(*it, fra)); - mj++; - if (mj == 4) { - mi++; - mj = 0; - } - fcurve_is_used(*it); - } - unit_converter->dae_matrix_to_mat4_(mat, matrix); - return true; - } - } - - if (is_scale) - size_to_mat4(mat, vec); - else - copy_v3_v3(mat[3], vec); - - return is_scale || is_translate; - } - - return false; + const COLLADAFW::UniqueId &listid = tm->getAnimationList(); + COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); + + if (type != COLLADAFW::Transformation::ROTATE && type != COLLADAFW::Transformation::SCALE && + type != COLLADAFW::Transformation::TRANSLATE && type != COLLADAFW::Transformation::MATRIX) { + fprintf(stderr, "animation of transformation %d is not supported yet\n", type); + return false; + } + + if (animlist_map.find(listid) == animlist_map.end()) + return false; + + const COLLADAFW::AnimationList *animlist = animlist_map[listid]; + const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings(); + + if (bindings.getCount()) { + float vec[3]; + + bool is_scale = (type == COLLADAFW::Transformation::SCALE); + bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE); + + if (is_scale) + dae_scale_to_v3(tm, vec); + else if (is_translate) + dae_translate_to_v3(tm, vec); + + for (unsigned int index = 0; index < bindings.getCount(); index++) { + const COLLADAFW::AnimationList::AnimationBinding &binding = bindings[index]; + std::vector<FCurve *> &curves = curve_map[binding.animation]; + COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass; + char path[100]; + + switch (type) { + case COLLADAFW::Transformation::ROTATE: + BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, index); + break; + case COLLADAFW::Transformation::SCALE: + BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, index); + break; + case COLLADAFW::Transformation::TRANSLATE: + BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, index); + break; + case COLLADAFW::Transformation::MATRIX: + BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, index); + break; + default: + break; + } + + if (type == COLLADAFW::Transformation::ROTATE) { + if (curves.size() != 1) { + fprintf(stderr, "expected 1 curve, got %d\n", (int)curves.size()); + return false; + } + + // TODO support other animclasses + if (animclass != COLLADAFW::AnimationList::ANGLE) { + report_class_type_unsupported(path, animclass, type); + return false; + } + + COLLADABU::Math::Vector3 &axis = ((COLLADAFW::Rotate *)tm)->getRotationAxis(); + + float ax[3] = {(float)axis[0], (float)axis[1], (float)axis[2]}; + float angle = evaluate_fcurve(curves[0], fra); + axis_angle_to_mat4(mat, ax, angle); + + return true; + } + else if (is_scale || is_translate) { + bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ; + + if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) { + if (is_xyz) + fprintf(stderr, "%s: expected 3 curves, got %d\n", path, (int)curves.size()); + else + fprintf(stderr, "%s: expected 1 curve, got %d\n", path, (int)curves.size()); + return false; + } + + switch (animclass) { + case COLLADAFW::AnimationList::POSITION_X: + vec[0] = evaluate_fcurve(curves[0], fra); + break; + case COLLADAFW::AnimationList::POSITION_Y: + vec[1] = evaluate_fcurve(curves[0], fra); + break; + case COLLADAFW::AnimationList::POSITION_Z: + vec[2] = evaluate_fcurve(curves[0], fra); + break; + case COLLADAFW::AnimationList::POSITION_XYZ: + vec[0] = evaluate_fcurve(curves[0], fra); + vec[1] = evaluate_fcurve(curves[1], fra); + vec[2] = evaluate_fcurve(curves[2], fra); + break; + default: + report_class_type_unsupported(path, animclass, type); + break; + } + } + else if (type == COLLADAFW::Transformation::MATRIX) { + // for now, of matrix animation, support only the case when all values are packed into one animation + if (curves.size() != 16) { + fprintf(stderr, "%s: expected 16 curves, got %d\n", path, (int)curves.size()); + return false; + } + + COLLADABU::Math::Matrix4 matrix; + int mi = 0, mj = 0; + + for (std::vector<FCurve *>::iterator it = curves.begin(); it != curves.end(); it++) { + matrix.setElement(mi, mj, evaluate_fcurve(*it, fra)); + mj++; + if (mj == 4) { + mi++; + mj = 0; + } + fcurve_is_used(*it); + } + unit_converter->dae_matrix_to_mat4_(mat, matrix); + return true; + } + } + + if (is_scale) + size_to_mat4(mat, vec); + else + copy_v3_v3(mat[3], vec); + + return is_scale || is_translate; + } + + return false; } // gives a world-space mat of joint at rest position -void AnimationImporter::get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node) +void AnimationImporter::get_joint_rest_mat(float mat[4][4], + COLLADAFW::Node *root, + COLLADAFW::Node *node) { - // if bind mat is not available, - // use "current" node transform, i.e. all those tms listed inside <node> - if (!armature_importer->get_joint_bind_mat(mat, node)) { - float par[4][4], m[4][4]; - - calc_joint_parent_mat_rest(par, NULL, root, node); - get_node_mat(m, node, NULL, NULL); - mul_m4_m4m4(mat, par, m); - } + // if bind mat is not available, + // use "current" node transform, i.e. all those tms listed inside <node> + if (!armature_importer->get_joint_bind_mat(mat, node)) { + float par[4][4], m[4][4]; + + calc_joint_parent_mat_rest(par, NULL, root, node); + get_node_mat(m, node, NULL, NULL); + mul_m4_m4m4(mat, par, m); + } } // gives a world-space mat, end's mat not included -bool AnimationImporter::calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end) +bool AnimationImporter::calc_joint_parent_mat_rest(float mat[4][4], + float par[4][4], + COLLADAFW::Node *node, + COLLADAFW::Node *end) { - float m[4][4]; - - if (node == end) { - par ? copy_m4_m4(mat, par) : unit_m4(mat); - return true; - } - - // use bind matrix if available or calc "current" world mat - if (!armature_importer->get_joint_bind_mat(m, node)) { - if (par) { - float temp[4][4]; - get_node_mat(temp, node, NULL, NULL); - mul_m4_m4m4(m, par, temp); - } - else { - get_node_mat(m, node, NULL, NULL); - } - } - - COLLADAFW::NodePointerArray& children = node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { - if (calc_joint_parent_mat_rest(mat, m, children[i], end)) - return true; - } - - return false; + float m[4][4]; + + if (node == end) { + par ? copy_m4_m4(mat, par) : unit_m4(mat); + return true; + } + + // use bind matrix if available or calc "current" world mat + if (!armature_importer->get_joint_bind_mat(m, node)) { + if (par) { + float temp[4][4]; + get_node_mat(temp, node, NULL, NULL); + mul_m4_m4m4(m, par, temp); + } + else { + get_node_mat(m, node, NULL, NULL); + } + } + + COLLADAFW::NodePointerArray &children = node->getChildNodes(); + for (unsigned int i = 0; i < children.getCount(); i++) { + if (calc_joint_parent_mat_rest(mat, m, children[i], end)) + return true; + } + + return false; } #ifdef ARMATURE_TEST -Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job) +Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, + COLLADAFW::Node *node, + Object *par_job) { - if (joint_objects.find(node->getUniqueId()) == joint_objects.end()) { - Object *job = bc_add_object(scene, OB_EMPTY, (char *)get_joint_name(node)); + if (joint_objects.find(node->getUniqueId()) == joint_objects.end()) { + Object *job = bc_add_object(scene, OB_EMPTY, (char *)get_joint_name(node)); - job->lay = BKE_scene_base_find(scene, job)->lay = 2; + job->lay = BKE_scene_base_find(scene, job)->lay = 2; - mul_v3_fl(job->scale, 0.5f); - DEG_id_tag_update(&job->id, ID_RECALC_TRANSFORM); + mul_v3_fl(job->scale, 0.5f); + DEG_id_tag_update(&job->id, ID_RECALC_TRANSFORM); - verify_adt_action((ID *)&job->id, 1); + verify_adt_action((ID *)&job->id, 1); - job->rotmode = ROT_MODE_QUAT; + job->rotmode = ROT_MODE_QUAT; - float mat[4][4]; - get_joint_rest_mat(mat, root, node); + float mat[4][4]; + get_joint_rest_mat(mat, root, node); - if (par_job) { - float temp[4][4], ipar[4][4]; - invert_m4_m4(ipar, par_job->obmat); - copy_m4_m4(temp, mat); - mul_m4_m4m4(mat, ipar, temp); - } + if (par_job) { + float temp[4][4], ipar[4][4]; + invert_m4_m4(ipar, par_job->obmat); + copy_m4_m4(temp, mat); + mul_m4_m4m4(mat, ipar, temp); + } - bc_decompose(mat, job->loc, NULL, job->quat, job->scale); + bc_decompose(mat, job->loc, NULL, job->quat, job->scale); - if (par_job) { - job->parent = par_job; + if (par_job) { + job->parent = par_job; - DEG_id_tag_update(&par_job->id, ID_RECALC_TRANSFORM); - job->parsubstr[0] = 0; - } + DEG_id_tag_update(&par_job->id, ID_RECALC_TRANSFORM); + job->parsubstr[0] = 0; + } - BKE_object_where_is_calc(scene, job); + BKE_object_where_is_calc(scene, job); - // after parenting and layer change - DEG_relations_tag_update(CTX_data_main(C)); + // after parenting and layer change + DEG_relations_tag_update(CTX_data_main(C)); - joint_objects[node->getUniqueId()] = job; - } + joint_objects[node->getUniqueId()] = job; + } - return joint_objects[node->getUniqueId()]; + return joint_objects[node->getUniqueId()]; } #endif @@ -1981,59 +2047,62 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No // mat must be identity on enter, node must be root bool AnimationImporter::evaluate_joint_world_transform_at_frame(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra) { - float m[4][4]; - if (par) { - float temp[4][4]; - evaluate_transform_at_frame(temp, node, node == end ? fra : 0.0f); - mul_m4_m4m4(m, par, temp); - } - else { - evaluate_transform_at_frame(m, node, node == end ? fra : 0.0f); - } - - if (node == end) { - copy_m4_m4(mat, m); - return true; - } - else { - COLLADAFW::NodePointerArray& children = node->getChildNodes(); - for (int i = 0; i < children.getCount(); i++) { - if (evaluate_joint_world_transform_at_frame(mat, m, children[i], end, fra)) - return true; - } - } - - return false; + float m[4][4]; + if (par) { + float temp[4][4]; + evaluate_transform_at_frame(temp, node, node == end ? fra : 0.0f); + mul_m4_m4m4(m, par, temp); + } + else { + evaluate_transform_at_frame(m, node, node == end ? fra : 0.0f); + } + + if (node == end) { + copy_m4_m4(mat, m); + return true; + } + else { + COLLADAFW::NodePointerArray& children = node->getChildNodes(); + for (int i = 0; i < children.getCount(); i++) { + if (evaluate_joint_world_transform_at_frame(mat, m, children[i], end, fra)) + return true; + } + } + + return false; } #endif void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu) { - const char *bone_name = bc_get_joint_name(node); - bAction *act = ob->adt->action; - - /* try to find group */ - bActionGroup *grp = BKE_action_group_find_name(act, bone_name); - - /* no matching groups, so add one */ - if (grp == NULL) { - /* Add a new group, and make it active */ - grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup"); - - grp->flag = AGRP_SELECTED; - BLI_strncpy(grp->name, bone_name, sizeof(grp->name)); - - BLI_addtail(&act->groups, grp); - BLI_uniquename(&act->groups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.', - offsetof(bActionGroup, name), 64); - } - - /* add F-Curve to group */ - action_groups_add_channel(act, grp, fcu); + const char *bone_name = bc_get_joint_name(node); + bAction *act = ob->adt->action; + + /* try to find group */ + bActionGroup *grp = BKE_action_group_find_name(act, bone_name); + + /* no matching groups, so add one */ + if (grp == NULL) { + /* Add a new group, and make it active */ + grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup"); + + grp->flag = AGRP_SELECTED; + BLI_strncpy(grp->name, bone_name, sizeof(grp->name)); + + BLI_addtail(&act->groups, grp); + BLI_uniquename(&act->groups, + grp, + CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), + '.', + offsetof(bActionGroup, name), + 64); + } + + /* add F-Curve to group */ + action_groups_add_channel(act, grp, fcu); } - void AnimationImporter::set_import_from_version(std::string import_from_version) { - this->import_from_version = import_from_version; + this->import_from_version = import_from_version; } diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h index dfb3f5cfe33..65e9974aec1 100644 --- a/source/blender/collada/AnimationImporter.h +++ b/source/blender/collada/AnimationImporter.h @@ -51,173 +51,199 @@ extern "C" { class ArmatureImporter; -class AnimationImporterBase -{ -public: - // virtual void change_eul_to_quat(Object *ob, bAction *act) = 0; +class AnimationImporterBase { + public: + // virtual void change_eul_to_quat(Object *ob, bAction *act) = 0; }; -class AnimationImporter : private TransformReader, public AnimationImporterBase -{ -private: - bContext *mContext; - ArmatureImporter *armature_importer; - Scene *scene; - - std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > curve_map; - std::map<COLLADAFW::UniqueId, TransformReader::Animation> uid_animated_map; - // std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map; - std::map<COLLADAFW::UniqueId, const COLLADAFW::AnimationList*> animlist_map; - std::vector<FCurve*> unused_curves; - std::map<COLLADAFW::UniqueId, Object*> joint_objects; - - FCurve *create_fcurve(int array_index, const char *rna_path); - - void add_bezt(FCurve *fcu, float frame, float value, eBezTriple_Interpolation ipo=BEZT_IPO_LIN); - - // create one or several fcurves depending on the number of parameters being animated - void animation_to_fcurves(COLLADAFW::AnimationCurve *curve); - - void fcurve_deg_to_rad(FCurve *cu); - - void fcurve_is_used(FCurve *fcu); - - void add_fcurves_to_object(Main *bmain, Object *ob, std::vector<FCurve*>& curves, char *rna_path, int array_index, Animation *animated); - - - int typeFlag; - - std::string import_from_version; - - enum lightAnim - { -// INANIMATE = 0, - LIGHT_COLOR = 2, - LIGHT_FOA = 4, - LIGHT_FOE = 8, - }; - - enum cameraAnim - { -// INANIMATE = 0, - CAMERA_XFOV = 2, - CAMERA_XMAG = 4, - CAMERA_YFOV = 8, - CAMERA_YMAG = 16, - CAMERA_ZFAR = 32, - CAMERA_ZNEAR = 64, - }; - - enum matAnim - { - MATERIAL_SHININESS = 2, - MATERIAL_SPEC_COLOR = 4, - MATERIAL_DIFF_COLOR = 1 << 3, - MATERIAL_TRANSPARENCY = 1 << 4, - MATERIAL_IOR = 1 << 5, - }; - - enum AnimationType - { - BC_INANIMATE = 0, - BC_NODE_TRANSFORM = 1, - }; - - struct AnimMix - { - int transform; - int light; - int camera; - int material; - int texture; - }; -public: - - AnimationImporter(bContext *C, UnitConverter *conv, ArmatureImporter *arm, Scene *scene) : - TransformReader(conv), - mContext(C), - armature_importer(arm), - scene(scene) {} - - ~AnimationImporter(); - - void set_import_from_version(std::string import_from_version); - bool write_animation(const COLLADAFW::Animation* anim); - - // called on post-process stage after writeVisualScenes - bool write_animation_list(const COLLADAFW::AnimationList* animlist); - - void read_node_transform(COLLADAFW::Node *node, Object *ob); +class AnimationImporter : private TransformReader, public AnimationImporterBase { + private: + bContext *mContext; + ArmatureImporter *armature_importer; + Scene *scene; + + std::map<COLLADAFW::UniqueId, std::vector<FCurve *>> curve_map; + std::map<COLLADAFW::UniqueId, TransformReader::Animation> uid_animated_map; + // std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map; + std::map<COLLADAFW::UniqueId, const COLLADAFW::AnimationList *> animlist_map; + std::vector<FCurve *> unused_curves; + std::map<COLLADAFW::UniqueId, Object *> joint_objects; + + FCurve *create_fcurve(int array_index, const char *rna_path); + + void add_bezt(FCurve *fcu, + float frame, + float value, + eBezTriple_Interpolation ipo = BEZT_IPO_LIN); + + // create one or several fcurves depending on the number of parameters being animated + void animation_to_fcurves(COLLADAFW::AnimationCurve *curve); + + void fcurve_deg_to_rad(FCurve *cu); + + void fcurve_is_used(FCurve *fcu); + + void add_fcurves_to_object(Main *bmain, + Object *ob, + std::vector<FCurve *> &curves, + char *rna_path, + int array_index, + Animation *animated); + + int typeFlag; + + std::string import_from_version; + + enum lightAnim { + // INANIMATE = 0, + LIGHT_COLOR = 2, + LIGHT_FOA = 4, + LIGHT_FOE = 8, + }; + + enum cameraAnim { + // INANIMATE = 0, + CAMERA_XFOV = 2, + CAMERA_XMAG = 4, + CAMERA_YFOV = 8, + CAMERA_YMAG = 16, + CAMERA_ZFAR = 32, + CAMERA_ZNEAR = 64, + }; + + enum matAnim { + MATERIAL_SHININESS = 2, + MATERIAL_SPEC_COLOR = 4, + MATERIAL_DIFF_COLOR = 1 << 3, + MATERIAL_TRANSPARENCY = 1 << 4, + MATERIAL_IOR = 1 << 5, + }; + + enum AnimationType { + BC_INANIMATE = 0, + BC_NODE_TRANSFORM = 1, + }; + + struct AnimMix { + int transform; + int light; + int camera; + int material; + int texture; + }; + + public: + AnimationImporter(bContext *C, UnitConverter *conv, ArmatureImporter *arm, Scene *scene) + : TransformReader(conv), mContext(C), armature_importer(arm), scene(scene) + { + } + + ~AnimationImporter(); + + void set_import_from_version(std::string import_from_version); + bool write_animation(const COLLADAFW::Animation *anim); + + // called on post-process stage after writeVisualScenes + bool write_animation_list(const COLLADAFW::AnimationList *animlist); + + void read_node_transform(COLLADAFW::Node *node, Object *ob); #if 0 - virtual void change_eul_to_quat(Object *ob, bAction *act); + virtual void change_eul_to_quat(Object *ob, bAction *act); #endif - void translate_Animations(COLLADAFW::Node * Node, - std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map, - std::multimap<COLLADAFW::UniqueId, Object*>& object_map, - std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map, - std::map<COLLADAFW::UniqueId, Material*> uid_material_map); - - AnimMix* get_animation_type( const COLLADAFW::Node * node, std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map ); - - void apply_matrix_curves(Object *ob, std::vector<FCurve*>& animcurves, COLLADAFW::Node* root, COLLADAFW::Node* node, - COLLADAFW::Transformation * tm ); - - void add_bone_animation_sampled(Object *ob, std::vector<FCurve*>& animcurves, COLLADAFW::Node* root, COLLADAFW::Node* node, COLLADAFW::Transformation * tm); - - void Assign_transform_animations(COLLADAFW::Transformation* transform, - const COLLADAFW::AnimationList::AnimationBinding *binding, - std::vector<FCurve*>* curves, bool is_joint, char *joint_path); - - void Assign_color_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char * anim_type); - void Assign_float_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char * anim_type); - void Assign_lens_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const double aspect, Camera *cam, const char *anim_type, int fov_type); - - int setAnimType ( const COLLADAFW::Animatable * prop, int type, int addition); - - void modify_fcurve(std::vector<FCurve*>* curves, const char *rna_path, int array_index ); - void unused_fcurve(std::vector<FCurve*>* curves ); - // prerequisites: - // animlist_map - map animlist id -> animlist - // curve_map - map anim id -> curve(s) - Object *translate_animation_OLD( - COLLADAFW::Node *node, - std::map<COLLADAFW::UniqueId, Object *>& object_map, - std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map, - COLLADAFW::Transformation::TransformationType tm_type, - Object *par_job = NULL); - - void find_frames( std::vector<float>* frames, std::vector<FCurve*>* curves ); - void find_frames_old( std::vector<float>* frames, COLLADAFW::Node * node, COLLADAFW::Transformation::TransformationType tm_type ); - // internal, better make it private - // warning: evaluates only rotation - // prerequisites: animlist_map, curve_map - void evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra); - - // return true to indicate that mat contains a sane value - bool evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra, const char *node_id); - - // gives a world-space mat of joint at rest position - void get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node); - - // gives a world-space mat, end's mat not included - bool calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end); - - float convert_to_focal_length(float in_xfov, int fov_type, float aspect, float sensorx); + void translate_Animations(COLLADAFW::Node *Node, + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &root_map, + std::multimap<COLLADAFW::UniqueId, Object *> &object_map, + std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map, + std::map<COLLADAFW::UniqueId, Material *> uid_material_map); + + AnimMix *get_animation_type( + const COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map); + + void apply_matrix_curves(Object *ob, + std::vector<FCurve *> &animcurves, + COLLADAFW::Node *root, + COLLADAFW::Node *node, + COLLADAFW::Transformation *tm); + + void add_bone_animation_sampled(Object *ob, + std::vector<FCurve *> &animcurves, + COLLADAFW::Node *root, + COLLADAFW::Node *node, + COLLADAFW::Transformation *tm); + + void Assign_transform_animations(COLLADAFW::Transformation *transform, + const COLLADAFW::AnimationList::AnimationBinding *binding, + std::vector<FCurve *> *curves, + bool is_joint, + char *joint_path); + + void Assign_color_animations(const COLLADAFW::UniqueId &listid, + ListBase *AnimCurves, + const char *anim_type); + void Assign_float_animations(const COLLADAFW::UniqueId &listid, + ListBase *AnimCurves, + const char *anim_type); + void Assign_lens_animations(const COLLADAFW::UniqueId &listid, + ListBase *AnimCurves, + const double aspect, + Camera *cam, + const char *anim_type, + int fov_type); + + int setAnimType(const COLLADAFW::Animatable *prop, int type, int addition); + + void modify_fcurve(std::vector<FCurve *> *curves, const char *rna_path, int array_index); + void unused_fcurve(std::vector<FCurve *> *curves); + // prerequisites: + // animlist_map - map animlist id -> animlist + // curve_map - map anim id -> curve(s) + Object *translate_animation_OLD(COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Object *> &object_map, + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &root_map, + COLLADAFW::Transformation::TransformationType tm_type, + Object *par_job = NULL); + + void find_frames(std::vector<float> *frames, std::vector<FCurve *> *curves); + void find_frames_old(std::vector<float> *frames, + COLLADAFW::Node *node, + COLLADAFW::Transformation::TransformationType tm_type); + // internal, better make it private + // warning: evaluates only rotation + // prerequisites: animlist_map, curve_map + void evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra); + + // return true to indicate that mat contains a sane value + bool evaluate_animation(COLLADAFW::Transformation *tm, + float mat[4][4], + float fra, + const char *node_id); + + // gives a world-space mat of joint at rest position + void get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node); + + // gives a world-space mat, end's mat not included + bool calc_joint_parent_mat_rest(float mat[4][4], + float par[4][4], + COLLADAFW::Node *node, + COLLADAFW::Node *end); + + float convert_to_focal_length(float in_xfov, int fov_type, float aspect, float sensorx); #ifdef ARMATURE_TEST - Object *get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job); + Object *get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job); #endif #if 0 - // recursively evaluates joint tree until end is found, mat then is world-space matrix of end - // mat must be identity on enter, node must be root - bool evaluate_joint_world_transform_at_frame(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra); + // recursively evaluates joint tree until end is found, mat then is world-space matrix of end + // mat must be identity on enter, node must be root + bool evaluate_joint_world_transform_at_frame(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra); #endif - void add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu); + void add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu); - void extra_data_importer(std::string elementName); + void extra_data_importer(std::string elementName); }; #endif diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index de4c4794547..ea1e98caf58 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - #include "COLLADASWBaseInputElement.h" #include "COLLADASWInstanceController.h" #include "COLLADASWPrimitves.h" @@ -47,263 +46,263 @@ extern "C" { #include "collada_utils.h" // write bone nodes -void ArmatureExporter::add_armature_bones( - Object *ob_arm, - ViewLayer *view_layer, - SceneExporter *se, - std::vector<Object *>& child_objects) +void ArmatureExporter::add_armature_bones(Object *ob_arm, + ViewLayer *view_layer, + SceneExporter *se, + std::vector<Object *> &child_objects) { - // write bone nodes + // write bone nodes - bArmature *armature = (bArmature *)ob_arm->data; - bool is_edited = armature->edbo != NULL; + bArmature *armature = (bArmature *)ob_arm->data; + bool is_edited = armature->edbo != NULL; - if (!is_edited) { - ED_armature_to_edit(armature); - } + if (!is_edited) { + ED_armature_to_edit(armature); + } - for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) { - // start from root bones - if (!bone->parent) { - add_bone_node(bone, ob_arm, se, child_objects); - } - } + for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) { + // start from root bones + if (!bone->parent) { + add_bone_node(bone, ob_arm, se, child_objects); + } + } - if (!is_edited) { - ED_armature_edit_free(armature); - } + if (!is_edited) { + ED_armature_edit_free(armature); + } } -void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) +void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, + Object *ob_arm, + Bone *bone) { - if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) { - std::string joint_id = translate_id(id_name(ob_arm) + "_" + bone->name); - ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, joint_id)); - } - else { - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - write_bone_URLs(ins, ob_arm, child); - } - } + if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) { + std::string joint_id = translate_id(id_name(ob_arm) + "_" + bone->name); + ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, joint_id)); + } + else { + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + write_bone_URLs(ins, ob_arm, child); + } + } } bool ArmatureExporter::add_instance_controller(Object *ob) { - Object *ob_arm = bc_get_assigned_armature(ob); - bArmature *arm = (bArmature *)ob_arm->data; + Object *ob_arm = bc_get_assigned_armature(ob); + bArmature *arm = (bArmature *)ob_arm->data; - const std::string& controller_id = get_controller_id(ob_arm, ob); + const std::string &controller_id = get_controller_id(ob_arm, ob); - COLLADASW::InstanceController ins(mSW); - ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); + COLLADASW::InstanceController ins(mSW); + ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); - Mesh *me = (Mesh *)ob->data; - if (!me->dvert) return false; + Mesh *me = (Mesh *)ob->data; + if (!me->dvert) + return false; - // write root bone URLs - Bone *bone; - for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { - write_bone_URLs(ins, ob_arm, bone); - } + // write root bone URLs + Bone *bone; + for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { + write_bone_URLs(ins, ob_arm, bone); + } - InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings( + ins.getBindMaterial(), ob, this->export_settings->active_uv_only); - ins.add(); - return true; + ins.add(); + return true; } #if 0 void ArmatureExporter::operator()(Object *ob) { - Object *ob_arm = bc_get_assigned_armature(ob); + Object *ob_arm = bc_get_assigned_armature(ob); } bool ArmatureExporter::already_written(Object *ob_arm) { - return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end(); + return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end(); } void ArmatureExporter::wrote(Object *ob_arm) { - written_armatures.push_back(ob_arm); + written_armatures.push_back(ob_arm); } void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce) { - objects.clear(); + objects.clear(); - Base *base = (Base *) sce->base.first; - while (base) { - Object *ob = base->object; + Base *base = (Base *) sce->base.first; + while (base) { + Object *ob = base->object; - if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) { - objects.push_back(ob); - } + if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) { + objects.push_back(ob); + } - base = base->next; - } + base = base->next; + } } #endif // parent_mat is armature-space -void ArmatureExporter::add_bone_node( - Bone *bone, - Object *ob_arm, - SceneExporter *se, - std::vector<Object *>& child_objects) +void ArmatureExporter::add_bone_node(Bone *bone, + Object *ob_arm, + SceneExporter *se, + std::vector<Object *> &child_objects) { - if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) { - std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name); - std::string node_name = std::string(bone->name); - std::string node_sid = get_joint_sid(bone); - - COLLADASW::Node node(mSW); - - node.setType(COLLADASW::Node::JOINT); - node.setNodeId(node_id); - node.setNodeName(node_name); - node.setNodeSid(node_sid); - - if (this->export_settings->use_blender_profile) - { - if (bone->parent) { - if (bone->flag & BONE_CONNECTED) { - node.addExtraTechniqueParameter("blender", "connect", true); - } - } - std::string layers = BoneExtended::get_bone_layers(bone->layer); - node.addExtraTechniqueParameter("blender", "layer", layers); - - bArmature *armature = (bArmature *)ob_arm->data; - EditBone *ebone = bc_get_edit_bone(armature, bone->name); - if (ebone && ebone->roll != 0) - { - node.addExtraTechniqueParameter("blender", "roll", ebone->roll); - } - if (bc_is_leaf_bone(bone)) - { - node.addExtraTechniqueParameter("blender", "tip_x", bone->arm_tail[0] - bone->arm_head[0]); - node.addExtraTechniqueParameter("blender", "tip_y", bone->arm_tail[1] - bone->arm_head[1]); - node.addExtraTechniqueParameter("blender", "tip_z", bone->arm_tail[2] - bone->arm_head[2]); - } - } - - node.start(); - - add_bone_transform(ob_arm, bone, node); - - // Write nodes of childobjects, remove written objects from list - std::vector<Object *>::iterator i = child_objects.begin(); - - while (i != child_objects.end()) { - if ((*i)->partype == PARBONE && STREQ((*i)->parsubstr, bone->name)) { - float backup_parinv[4][4]; - copy_m4_m4(backup_parinv, (*i)->parentinv); - - // crude, temporary change to parentinv - // so transform gets exported correctly. - - // Add bone tail- translation... don't know why - // bone parenting is against the tail of a bone - // and not it's head, seems arbitrary. - (*i)->parentinv[3][1] += bone->length; - - // OPEN_SIM_COMPATIBILITY - // TODO: when such objects are animated as - // single matrix the tweak must be applied - // to the result. - if (export_settings->open_sim) { - // tweak objects parentinverse to match compatibility - float temp[4][4]; - - copy_m4_m4(temp, bone->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - - mul_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv); - } - - se->writeNodes(*i); - copy_m4_m4((*i)->parentinv, backup_parinv); - i = child_objects.erase(i); - } - else i++; - } - - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - add_bone_node(child, ob_arm, se, child_objects); - } - node.end(); - } - else { - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - add_bone_node(child, ob_arm, se, child_objects); - } - } + if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) { + std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name); + std::string node_name = std::string(bone->name); + std::string node_sid = get_joint_sid(bone); + + COLLADASW::Node node(mSW); + + node.setType(COLLADASW::Node::JOINT); + node.setNodeId(node_id); + node.setNodeName(node_name); + node.setNodeSid(node_sid); + + if (this->export_settings->use_blender_profile) { + if (bone->parent) { + if (bone->flag & BONE_CONNECTED) { + node.addExtraTechniqueParameter("blender", "connect", true); + } + } + std::string layers = BoneExtended::get_bone_layers(bone->layer); + node.addExtraTechniqueParameter("blender", "layer", layers); + + bArmature *armature = (bArmature *)ob_arm->data; + EditBone *ebone = bc_get_edit_bone(armature, bone->name); + if (ebone && ebone->roll != 0) { + node.addExtraTechniqueParameter("blender", "roll", ebone->roll); + } + if (bc_is_leaf_bone(bone)) { + node.addExtraTechniqueParameter("blender", "tip_x", bone->arm_tail[0] - bone->arm_head[0]); + node.addExtraTechniqueParameter("blender", "tip_y", bone->arm_tail[1] - bone->arm_head[1]); + node.addExtraTechniqueParameter("blender", "tip_z", bone->arm_tail[2] - bone->arm_head[2]); + } + } + + node.start(); + + add_bone_transform(ob_arm, bone, node); + + // Write nodes of childobjects, remove written objects from list + std::vector<Object *>::iterator i = child_objects.begin(); + + while (i != child_objects.end()) { + if ((*i)->partype == PARBONE && STREQ((*i)->parsubstr, bone->name)) { + float backup_parinv[4][4]; + copy_m4_m4(backup_parinv, (*i)->parentinv); + + // crude, temporary change to parentinv + // so transform gets exported correctly. + + // Add bone tail- translation... don't know why + // bone parenting is against the tail of a bone + // and not it's head, seems arbitrary. + (*i)->parentinv[3][1] += bone->length; + + // OPEN_SIM_COMPATIBILITY + // TODO: when such objects are animated as + // single matrix the tweak must be applied + // to the result. + if (export_settings->open_sim) { + // tweak objects parentinverse to match compatibility + float temp[4][4]; + + copy_m4_m4(temp, bone->arm_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + + mul_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv); + } + + se->writeNodes(*i); + copy_m4_m4((*i)->parentinv, backup_parinv); + i = child_objects.erase(i); + } + else + i++; + } + + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + add_bone_node(child, ob_arm, se, child_objects); + } + node.end(); + } + else { + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + add_bone_node(child, ob_arm, se, child_objects); + } + } } -void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node) +void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node &node) { - //bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); - - float mat[4][4]; - float bone_rest_mat[4][4]; /* derived from bone->arm_mat */ - float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */ - - bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat); + //bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); - if (!has_restmat) { + float mat[4][4]; + float bone_rest_mat[4][4]; /* derived from bone->arm_mat */ + float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */ - /* Have no restpose matrix stored, try old style <= Blender 2.78 */ + bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat); - bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true); + if (!has_restmat) { - if (bone->parent) { - // get bone-space matrix from parent pose - /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); - float invpar[4][4]; - invert_m4_m4(invpar, parchan->pose_mat); - mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ - float invpar[4][4]; - bc_create_restpose_mat(this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true); + /* Have no restpose matrix stored, try old style <= Blender 2.78 */ - invert_m4_m4(invpar, parent_rest_mat); - mul_m4_m4m4(mat, invpar, bone_rest_mat); + bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true); - } - else { - copy_m4_m4(mat, bone_rest_mat); - } + if (bone->parent) { + // get bone-space matrix from parent pose + /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); + float invpar[4][4]; + invert_m4_m4(invpar, parchan->pose_mat); + mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ + float invpar[4][4]; + bc_create_restpose_mat( + this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true); - // OPEN_SIM_COMPATIBILITY - if (export_settings->open_sim) { - // Remove rotations vs armature from transform - // parent_rest_rot * mat * irest_rot - float temp[4][4]; - copy_m4_m4(temp, bone_rest_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - invert_m4(temp); + invert_m4_m4(invpar, parent_rest_mat); + mul_m4_m4m4(mat, invpar, bone_rest_mat); + } + else { + copy_m4_m4(mat, bone_rest_mat); + } - mul_m4_m4m4(mat, mat, temp); + // OPEN_SIM_COMPATIBILITY + if (export_settings->open_sim) { + // Remove rotations vs armature from transform + // parent_rest_rot * mat * irest_rot + float temp[4][4]; + copy_m4_m4(temp, bone_rest_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + invert_m4(temp); - if (bone->parent) { - copy_m4_m4(temp, parent_rest_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + mul_m4_m4m4(mat, mat, temp); - mul_m4_m4m4(mat, temp, mat); - } - } - } + if (bone->parent) { + copy_m4_m4(temp, parent_rest_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - if (this->export_settings->limit_precision) - bc_sanitize_mat(mat, LIMITTED_PRECISION); + mul_m4_m4m4(mat, temp, mat); + } + } + } - TransformWriter::add_node_transform(node, mat, NULL); + if (this->export_settings->limit_precision) + bc_sanitize_mat(mat, LIMITTED_PRECISION); + TransformWriter::add_node_transform(node, mat, NULL); } std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob) { - return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX; + return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + + SKIN_CONTROLLER_ID_SUFFIX; } diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 11f853621a0..f0da8680476 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -47,54 +47,55 @@ class SceneExporter; // XXX exporter writes wrong data for shared armatures. A separate // controller should be written for each armature-mesh binding how do // we make controller ids then? -class ArmatureExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter -{ -public: - - // XXX exporter writes wrong data for shared armatures. A separate - // controller should be written for each armature-mesh binding how do - // we make controller ids then? - ArmatureExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : - COLLADASW::LibraryControllers(sw), - blender_context(blender_context), - export_settings(export_settings) - {} - - void add_armature_bones( - Object *ob_arm, - ViewLayer *view_layer, - SceneExporter *se, - std::vector<Object *>& child_objects); - - bool add_instance_controller(Object *ob); - -private: - BlenderContext &blender_context; - const ExportSettings *export_settings; +class ArmatureExporter : public COLLADASW::LibraryControllers, + protected TransformWriter, + protected InstanceWriter { + public: + // XXX exporter writes wrong data for shared armatures. A separate + // controller should be written for each armature-mesh binding how do + // we make controller ids then? + ArmatureExporter(BlenderContext &blender_context, + COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings) + : COLLADASW::LibraryControllers(sw), + blender_context(blender_context), + export_settings(export_settings) + { + } + + void add_armature_bones(Object *ob_arm, + ViewLayer *view_layer, + SceneExporter *se, + std::vector<Object *> &child_objects); + + bool add_instance_controller(Object *ob); + + private: + BlenderContext &blender_context; + const ExportSettings *export_settings; #if 0 - std::vector<Object *> written_armatures; + std::vector<Object *> written_armatures; - bool already_written(Object *ob_arm); + bool already_written(Object *ob_arm); - void wrote(Object *ob_arm); + void wrote(Object *ob_arm); - void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); + void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); #endif - // Scene, SceneExporter and the list of child_objects - // are required for writing bone parented objects - void add_bone_node( - Bone *bone, - Object *ob_arm, - SceneExporter *se, - std::vector<Object *>& child_objects); + // Scene, SceneExporter and the list of child_objects + // are required for writing bone parented objects + void add_bone_node(Bone *bone, + Object *ob_arm, + SceneExporter *se, + std::vector<Object *> &child_objects); - void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node); + void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node &node); - std::string get_controller_id(Object *ob_arm, Object *ob); + std::string get_controller_id(Object *ob_arm, Object *ob); - void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone); + void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone); }; #endif diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index bd06a8e5319..038dbd0c30d 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - /* COLLADABU_ASSERT, may be able to remove later */ #include "COLLADABUPlatform.h" @@ -41,170 +40,182 @@ extern "C" { #include "ArmatureImporter.h" // use node name, or fall back to original id if not present (name is optional) -template<class T> -static const char *bc_get_joint_name(T *node) +template<class T> static const char *bc_get_joint_name(T *node) { - const std::string& id = node->getName(); - return id.size() ? id.c_str() : node->getOriginalId().c_str(); + const std::string &id = node->getName(); + return id.size() ? id.c_str() : node->getOriginalId().c_str(); } - -ArmatureImporter::ArmatureImporter( - UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings) : - TransformReader(conv), - m_bmain(bmain), - scene(sce), - view_layer(view_layer), - unit_converter(conv), - import_settings(import_settings), - empty(NULL), - mesh_importer(mesh) { +ArmatureImporter::ArmatureImporter(UnitConverter *conv, + MeshImporterBase *mesh, + Main *bmain, + Scene *sce, + ViewLayer *view_layer, + const ImportSettings *import_settings) + : TransformReader(conv), + m_bmain(bmain), + scene(sce), + view_layer(view_layer), + unit_converter(conv), + import_settings(import_settings), + empty(NULL), + mesh_importer(mesh) +{ } ArmatureImporter::~ArmatureImporter() { - // free skin controller data if we forget to do this earlier - std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; - for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { - it->second.free(); - } + // free skin controller data if we forget to do this earlier + std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; + for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { + it->second.free(); + } } #if 0 JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node); { - const COLLADAFW::UniqueId& joint_id = node->getUniqueId(); + const COLLADAFW::UniqueId& joint_id = node->getUniqueId(); - if (joint_id_to_joint_index_map.find(joint_id) == joint_id_to_joint_index_map.end()) { - fprintf(stderr, "Cannot find a joint index by joint id for %s.\n", - node->getOriginalId().c_str()); - return NULL; - } + if (joint_id_to_joint_index_map.find(joint_id) == joint_id_to_joint_index_map.end()) { + fprintf(stderr, "Cannot find a joint index by joint id for %s.\n", + node->getOriginalId().c_str()); + return NULL; + } - int joint_index = joint_id_to_joint_index_map[joint_id]; + int joint_index = joint_id_to_joint_index_map[joint_id]; - return &joint_index_to_joint_info_map[joint_index]; + return &joint_index_to_joint_info_map[joint_index]; } #endif -int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBone *parent, int totchild, - float parent_mat[4][4], bArmature *arm, std::vector<std::string> &layer_labels) +int ArmatureImporter::create_bone(SkinInfo *skin, + COLLADAFW::Node *node, + EditBone *parent, + int totchild, + float parent_mat[4][4], + bArmature *arm, + std::vector<std::string> &layer_labels) { - float mat[4][4]; - float joint_inv_bind_mat[4][4]; - float joint_bind_mat[4][4]; - int chain_length = 0; - - //Checking if bone is already made. - std::vector<COLLADAFW::Node *>::iterator it; - it = std::find(finished_joints.begin(), finished_joints.end(), node); - if (it != finished_joints.end()) return chain_length; - - EditBone *bone = ED_armature_ebone_add(arm, bc_get_joint_name(node)); - totbone++; - - /* - * We use the inv_bind_shape matrix to apply the armature bind pose as its rest pose. - */ - - std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it; - bool bone_is_skinned = false; - for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) { - - SkinInfo *b = &skin_it->second; - if (b->get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) { - - // get original world-space matrix - invert_m4_m4(mat, joint_inv_bind_mat); - copy_m4_m4(joint_bind_mat, mat); - // And make local to armature - Object *ob_arm = skin->BKE_armature_from_object(); - if (ob_arm) { - float invmat[4][4]; - invert_m4_m4(invmat, ob_arm->obmat); - mul_m4_m4m4(mat, invmat, mat); - } - - bone_is_skinned = true; - break; - } - } - - // create a bone even if there's no joint data for it (i.e. it has no influence) - if (!bone_is_skinned) { - get_node_mat(mat, node, NULL, NULL, parent_mat); - } - - if (parent) bone->parent = parent; - - float loc[3], size[3], rot[3][3]; - BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(arm); - BoneExtended &be = add_bone_extended(bone, node, totchild, layer_labels, extended_bones); - int layer = be.get_bone_layers(); - if (layer) bone->layer = layer; - arm->layer |= layer; // ensure that all populated bone layers are visible after import - - float *tail = be.get_tail(); - int use_connect = be.get_use_connect(); - - switch (use_connect) { - case 1: bone->flag |= BONE_CONNECTED; - break; - case -1:/* Connect type not specified */ - case 0: bone->flag &= ~BONE_CONNECTED; - break; - } - - if (be.has_roll()) { - bone->roll = be.get_roll(); - } - else { - float angle; - mat4_to_loc_rot_size(loc, rot, size, mat); - mat3_to_vec_roll(rot, NULL, &angle); - bone->roll = angle; - } - copy_v3_v3(bone->head, mat[3]); - - if (bone_is_skinned && this->import_settings->keep_bind_info) - { - float rest_mat[4][4]; - get_node_mat(rest_mat, node, NULL, NULL, NULL); - bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat); - bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat); - } - - add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero - - /* find smallest bone length in armature (used later for leaf bone length) */ - if (parent) { - - if (use_connect == 1) { - copy_v3_v3(parent->tail, bone->head); - } - - /* guess reasonable leaf bone length */ - float length = len_v3v3(parent->head, bone->head); - if ((length < leaf_bone_length || totbone == 0) && length > MINIMUM_BONE_LENGTH) { - leaf_bone_length = length; - } - } - - COLLADAFW::NodePointerArray& children = node->getChildNodes(); - - for (unsigned int i = 0; i < children.getCount(); i++) { - int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm, layer_labels); - if (cl > chain_length) - chain_length = cl; - } - - bone->length = len_v3v3(bone->head, bone->tail); - joint_by_uid[node->getUniqueId()] = node; - finished_joints.push_back(node); - - be.set_chain_length(chain_length + 1); - - return chain_length + 1; + float mat[4][4]; + float joint_inv_bind_mat[4][4]; + float joint_bind_mat[4][4]; + int chain_length = 0; + + //Checking if bone is already made. + std::vector<COLLADAFW::Node *>::iterator it; + it = std::find(finished_joints.begin(), finished_joints.end(), node); + if (it != finished_joints.end()) + return chain_length; + + EditBone *bone = ED_armature_ebone_add(arm, bc_get_joint_name(node)); + totbone++; + + /* + * We use the inv_bind_shape matrix to apply the armature bind pose as its rest pose. + */ + + std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it; + bool bone_is_skinned = false; + for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) { + + SkinInfo *b = &skin_it->second; + if (b->get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) { + + // get original world-space matrix + invert_m4_m4(mat, joint_inv_bind_mat); + copy_m4_m4(joint_bind_mat, mat); + // And make local to armature + Object *ob_arm = skin->BKE_armature_from_object(); + if (ob_arm) { + float invmat[4][4]; + invert_m4_m4(invmat, ob_arm->obmat); + mul_m4_m4m4(mat, invmat, mat); + } + + bone_is_skinned = true; + break; + } + } + + // create a bone even if there's no joint data for it (i.e. it has no influence) + if (!bone_is_skinned) { + get_node_mat(mat, node, NULL, NULL, parent_mat); + } + + if (parent) + bone->parent = parent; + + float loc[3], size[3], rot[3][3]; + BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(arm); + BoneExtended &be = add_bone_extended(bone, node, totchild, layer_labels, extended_bones); + int layer = be.get_bone_layers(); + if (layer) + bone->layer = layer; + arm->layer |= layer; // ensure that all populated bone layers are visible after import + + float *tail = be.get_tail(); + int use_connect = be.get_use_connect(); + + switch (use_connect) { + case 1: + bone->flag |= BONE_CONNECTED; + break; + case -1: /* Connect type not specified */ + case 0: + bone->flag &= ~BONE_CONNECTED; + break; + } + + if (be.has_roll()) { + bone->roll = be.get_roll(); + } + else { + float angle; + mat4_to_loc_rot_size(loc, rot, size, mat); + mat3_to_vec_roll(rot, NULL, &angle); + bone->roll = angle; + } + copy_v3_v3(bone->head, mat[3]); + + if (bone_is_skinned && this->import_settings->keep_bind_info) { + float rest_mat[4][4]; + get_node_mat(rest_mat, node, NULL, NULL, NULL); + bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat); + bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat); + } + + add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero + + /* find smallest bone length in armature (used later for leaf bone length) */ + if (parent) { + + if (use_connect == 1) { + copy_v3_v3(parent->tail, bone->head); + } + + /* guess reasonable leaf bone length */ + float length = len_v3v3(parent->head, bone->head); + if ((length < leaf_bone_length || totbone == 0) && length > MINIMUM_BONE_LENGTH) { + leaf_bone_length = length; + } + } + + COLLADAFW::NodePointerArray &children = node->getChildNodes(); + + for (unsigned int i = 0; i < children.getCount(); i++) { + int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm, layer_labels); + if (cl > chain_length) + chain_length = cl; + } + + bone->length = len_v3v3(bone->head, bone->tail); + joint_by_uid[node->getUniqueId()] = node; + finished_joints.push_back(node); + + be.set_chain_length(chain_length + 1); + + return chain_length + 1; } /** @@ -213,464 +224,473 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon * tail locations for the affected bones (nodes which don't have any connected child) * Hint: The extended_bones set gets populated in ArmatureImporter::create_bone */ -void ArmatureImporter::fix_leaf_bone_hierarchy(bArmature *armature, Bone *bone, bool fix_orientation) +void ArmatureImporter::fix_leaf_bone_hierarchy(bArmature *armature, + Bone *bone, + bool fix_orientation) { - if (bone == NULL) - return; - - if (bc_is_leaf_bone(bone)) { - BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); - BoneExtended *be = extended_bones[bone->name]; - EditBone *ebone = bc_get_edit_bone(armature, bone->name); - fix_leaf_bone(armature, ebone, be, fix_orientation); - } - - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - fix_leaf_bone_hierarchy(armature, child, fix_orientation); - } + if (bone == NULL) + return; + + if (bc_is_leaf_bone(bone)) { + BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); + BoneExtended *be = extended_bones[bone->name]; + EditBone *ebone = bc_get_edit_bone(armature, bone->name); + fix_leaf_bone(armature, ebone, be, fix_orientation); + } + + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + fix_leaf_bone_hierarchy(armature, child, fix_orientation); + } } -void ArmatureImporter::fix_leaf_bone(bArmature *armature, EditBone *ebone, BoneExtended *be , bool fix_orientation) +void ArmatureImporter::fix_leaf_bone(bArmature *armature, + EditBone *ebone, + BoneExtended *be, + bool fix_orientation) { - if (be == NULL || !be->has_tail()) { - - /* Collada only knows Joints, Here we guess a reasonable leaf bone length */ - float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length; - - - float vec[3]; - - if (fix_orientation && ebone->parent != NULL) { - EditBone *parent = ebone->parent; - sub_v3_v3v3(vec, ebone->head, parent->head); - if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH) - { - sub_v3_v3v3(vec, parent->tail, parent->head); - } - } - else { - vec[2] = 0.1f; - sub_v3_v3v3(vec, ebone->tail, ebone->head); - } - - normalize_v3_v3(vec, vec); - mul_v3_fl(vec, leaf_length); - add_v3_v3v3(ebone->tail, ebone->head, vec); - } + if (be == NULL || !be->has_tail()) { + + /* Collada only knows Joints, Here we guess a reasonable leaf bone length */ + float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length; + + float vec[3]; + + if (fix_orientation && ebone->parent != NULL) { + EditBone *parent = ebone->parent; + sub_v3_v3v3(vec, ebone->head, parent->head); + if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH) { + sub_v3_v3v3(vec, parent->tail, parent->head); + } + } + else { + vec[2] = 0.1f; + sub_v3_v3v3(vec, ebone->tail, ebone->head); + } + + normalize_v3_v3(vec, vec); + mul_v3_fl(vec, leaf_length); + add_v3_v3v3(ebone->tail, ebone->head, vec); + } } void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone) { - /* armature has no bones */ - if (bone == NULL) - return; - - if (bone->parent && bone->flag & BONE_CONNECTED) { - copy_v3_v3(bone->parent->tail, bone->head); - } + /* armature has no bones */ + if (bone == NULL) + return; - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - fix_parent_connect(armature, child); - } + if (bone->parent && bone->flag & BONE_CONNECTED) { + copy_v3_v3(bone->parent->tail, bone->head); + } + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + fix_parent_connect(armature, child); + } } void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip) { - BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); - BoneExtended *dominant_child = NULL; - int maxlen = 0; - - if (parentbone == NULL) - return; - - Bone *child = (Bone *)parentbone->childbase.first; - if (child && (import_settings->find_chains || child->next==NULL)) { - for (; child; child = child->next) { - BoneExtended *be = extended_bones[child->name]; - if (be != NULL) { - int chain_len = be->get_chain_length(); - if (chain_len <= clip) { - if (chain_len > maxlen) { - dominant_child = be; - maxlen = chain_len; - } - else if (chain_len == maxlen) { - dominant_child = NULL; - } - } - } - } - } - - BoneExtended *pbe = extended_bones[parentbone->name]; - if (dominant_child != NULL) { - /* Found a valid chain. Now connect current bone with that chain.*/ - EditBone *pebone = bc_get_edit_bone(armature, parentbone->name); - EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name()); - if (pebone && !(cebone->flag & BONE_CONNECTED)) { - float vec[3]; - sub_v3_v3v3(vec, cebone->head, pebone->head); - - /* - * It is possible that the child's head is located on the parents head. - * When this happens, then moving the parent's tail to the child's head - * would result in a zero sized bone and Blender would silently remove the bone. - * So we move the tail only when the resulting bone has a minimum length: - */ - - if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH) - { - copy_v3_v3(pebone->tail, cebone->head); - pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/ - if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) { - - BoneExtended *cbe = extended_bones[cebone->name]; - cbe->set_use_connect(true); - - cebone->flag |= BONE_CONNECTED; - pbe->set_leaf_bone(false); - printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name); - } - } - } - for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) { - ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX); - } - } - else if (maxlen>1 && maxlen > this->import_settings->min_chain_length) { - /* Try again with smaller chain length */ - ArmatureImporter::connect_bone_chains(armature, parentbone, maxlen - 1); - } - else { - /* can't connect this Bone. Proceed with children ... */ - if (pbe) pbe->set_leaf_bone(true); - for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) { - ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX); - } - } - + BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); + BoneExtended *dominant_child = NULL; + int maxlen = 0; + + if (parentbone == NULL) + return; + + Bone *child = (Bone *)parentbone->childbase.first; + if (child && (import_settings->find_chains || child->next == NULL)) { + for (; child; child = child->next) { + BoneExtended *be = extended_bones[child->name]; + if (be != NULL) { + int chain_len = be->get_chain_length(); + if (chain_len <= clip) { + if (chain_len > maxlen) { + dominant_child = be; + maxlen = chain_len; + } + else if (chain_len == maxlen) { + dominant_child = NULL; + } + } + } + } + } + + BoneExtended *pbe = extended_bones[parentbone->name]; + if (dominant_child != NULL) { + /* Found a valid chain. Now connect current bone with that chain.*/ + EditBone *pebone = bc_get_edit_bone(armature, parentbone->name); + EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name()); + if (pebone && !(cebone->flag & BONE_CONNECTED)) { + float vec[3]; + sub_v3_v3v3(vec, cebone->head, pebone->head); + + /* + * It is possible that the child's head is located on the parents head. + * When this happens, then moving the parent's tail to the child's head + * would result in a zero sized bone and Blender would silently remove the bone. + * So we move the tail only when the resulting bone has a minimum length: + */ + + if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH) { + copy_v3_v3(pebone->tail, cebone->head); + pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/ + if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) { + + BoneExtended *cbe = extended_bones[cebone->name]; + cbe->set_use_connect(true); + + cebone->flag |= BONE_CONNECTED; + pbe->set_leaf_bone(false); + printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name); + } + } + } + for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) { + ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX); + } + } + else if (maxlen > 1 && maxlen > this->import_settings->min_chain_length) { + /* Try again with smaller chain length */ + ArmatureImporter::connect_bone_chains(armature, parentbone, maxlen - 1); + } + else { + /* can't connect this Bone. Proceed with children ... */ + if (pbe) + pbe->set_leaf_bone(true); + for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) { + ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX); + } + } } #if 0 void ArmatureImporter::set_leaf_bone_shapes(Object *ob_arm) { - bPose *pose = ob_arm->pose; - - std::vector<LeafBone>::iterator it; - for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) { - LeafBone& leaf = *it; - - bPoseChannel *pchan = BKE_pose_channel_find_name(pose, leaf.name); - if (pchan) { - pchan->custom = get_empty_for_leaves(); - } - else { - fprintf(stderr, "Cannot find a pose channel for leaf bone %s\n", leaf.name); - } - } + bPose *pose = ob_arm->pose; + + std::vector<LeafBone>::iterator it; + for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) { + LeafBone& leaf = *it; + + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, leaf.name); + if (pchan) { + pchan->custom = get_empty_for_leaves(); + } + else { + fprintf(stderr, "Cannot find a pose channel for leaf bone %s\n", leaf.name); + } + } } void ArmatureImporter::set_euler_rotmode() { - // just set rotmode = ROT_MODE_EUL on pose channel for each joint + // just set rotmode = ROT_MODE_EUL on pose channel for each joint - std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>::iterator it; + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>::iterator it; - for (it = joint_by_uid.begin(); it != joint_by_uid.end(); it++) { + for (it = joint_by_uid.begin(); it != joint_by_uid.end(); it++) { - COLLADAFW::Node *joint = it->second; + COLLADAFW::Node *joint = it->second; - std::map<COLLADAFW::UniqueId, SkinInfo>::iterator sit; + std::map<COLLADAFW::UniqueId, SkinInfo>::iterator sit; - for (sit = skin_by_data_uid.begin(); sit != skin_by_data_uid.end(); sit++) { - SkinInfo& skin = sit->second; + for (sit = skin_by_data_uid.begin(); sit != skin_by_data_uid.end(); sit++) { + SkinInfo& skin = sit->second; - if (skin.uses_joint_or_descendant(joint)) { - bPoseChannel *pchan = skin.get_pose_channel_from_node(joint); + if (skin.uses_joint_or_descendant(joint)) { + bPoseChannel *pchan = skin.get_pose_channel_from_node(joint); - if (pchan) { - pchan->rotmode = ROT_MODE_EUL; - } - else { - fprintf(stderr, "Cannot find pose channel for %s.\n", get_joint_name(joint)); - } + if (pchan) { + pchan->rotmode = ROT_MODE_EUL; + } + else { + fprintf(stderr, "Cannot find pose channel for %s.\n", get_joint_name(joint)); + } - break; - } - } - } + break; + } + } + } } #endif Object *ArmatureImporter::get_empty_for_leaves() { - if (empty) return empty; + if (empty) + return empty; - empty = bc_add_object(m_bmain, scene, view_layer, OB_EMPTY, NULL); - empty->empty_drawtype = OB_EMPTY_SPHERE; + empty = bc_add_object(m_bmain, scene, view_layer, OB_EMPTY, NULL); + empty->empty_drawtype = OB_EMPTY_SPHERE; - return empty; + return empty; } #if 0 Object *ArmatureImporter::find_armature(COLLADAFW::Node *node) { - JointData *jd = get_joint_data(node); - if (jd) return jd->ob_arm; + JointData *jd = get_joint_data(node); + if (jd) return jd->ob_arm; - COLLADAFW::NodePointerArray& children = node->getChildNodes(); - for (int i = 0; i < children.getCount(); i++) { - Object *ob_arm = find_armature(children[i]); - if (ob_arm) return ob_arm; - } + COLLADAFW::NodePointerArray& children = node->getChildNodes(); + for (int i = 0; i < children.getCount(); i++) { + Object *ob_arm = find_armature(children[i]); + if (ob_arm) return ob_arm; + } - return NULL; + return NULL; } ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm) { - // try finding it - std::vector<ArmatureJoints>::iterator it; - for (it = armature_joints.begin(); it != armature_joints.end(); it++) { - if ((*it).ob_arm == ob_arm) return *it; - } - - // not found, create one - ArmatureJoints aj; - aj.ob_arm = ob_arm; - armature_joints.push_back(aj); - - return armature_joints.back(); + // try finding it + std::vector<ArmatureJoints>::iterator it; + for (it = armature_joints.begin(); it != armature_joints.end(); it++) { + if ((*it).ob_arm == ob_arm) return *it; + } + + // not found, create one + ArmatureJoints aj; + aj.ob_arm = ob_arm; + armature_joints.push_back(aj); + + return armature_joints.back(); } #endif void ArmatureImporter::create_armature_bones(Main *bmain, std::vector<Object *> &ob_arms) { - std::vector<COLLADAFW::Node *>::iterator ri; - std::vector<std::string> layer_labels; - - //if there is an armature created for root_joint next root_joint - for (ri = root_joints.begin(); ri != root_joints.end(); ri++) { - if (get_armature_for_joint(*ri) != NULL) continue; - - Object *ob_arm = joint_parent_map[(*ri)->getUniqueId()]; - if (!ob_arm) - continue; - - bArmature *armature = (bArmature *)ob_arm->data; - if (!armature) - continue; - - char *bone_name = (char *)bc_get_joint_name(*ri); - Bone *bone = BKE_armature_find_bone_name(armature, bone_name); - if (bone) { - fprintf(stderr, "Reuse of child bone [%s] as root bone in same Armature is not supported.\n", bone_name); - continue; - } - - ED_armature_to_edit(armature); - armature->layer = 0; // layer is set according to imported bone set in create_bone() - - create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels); - if (this->import_settings->find_chains) { - connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); - } - - /* exit armature edit mode to populate the Armature object */ - ED_armature_from_edit(bmain, armature); - ED_armature_edit_free(armature); - - ED_armature_to_edit(armature); - - fix_leaf_bone_hierarchy(armature, (Bone *)armature->bonebase.first, this->import_settings->fix_orientation); - unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm; - - ED_armature_from_edit(bmain, armature); - ED_armature_edit_free(armature); - - int index = std::find(ob_arms.begin(), ob_arms.end(), ob_arm) - ob_arms.begin(); - if (index == 0) { - ob_arms.push_back(ob_arm); - } - - DEG_id_tag_update(&ob_arm->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - } + std::vector<COLLADAFW::Node *>::iterator ri; + std::vector<std::string> layer_labels; + + //if there is an armature created for root_joint next root_joint + for (ri = root_joints.begin(); ri != root_joints.end(); ri++) { + if (get_armature_for_joint(*ri) != NULL) + continue; + + Object *ob_arm = joint_parent_map[(*ri)->getUniqueId()]; + if (!ob_arm) + continue; + + bArmature *armature = (bArmature *)ob_arm->data; + if (!armature) + continue; + + char *bone_name = (char *)bc_get_joint_name(*ri); + Bone *bone = BKE_armature_find_bone_name(armature, bone_name); + if (bone) { + fprintf(stderr, + "Reuse of child bone [%s] as root bone in same Armature is not supported.\n", + bone_name); + continue; + } + + ED_armature_to_edit(armature); + armature->layer = 0; // layer is set according to imported bone set in create_bone() + + create_bone(NULL, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels); + if (this->import_settings->find_chains) { + connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); + } + + /* exit armature edit mode to populate the Armature object */ + ED_armature_from_edit(bmain, armature); + ED_armature_edit_free(armature); + + ED_armature_to_edit(armature); + + fix_leaf_bone_hierarchy( + armature, (Bone *)armature->bonebase.first, this->import_settings->fix_orientation); + unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm; + + ED_armature_from_edit(bmain, armature); + ED_armature_edit_free(armature); + + int index = std::find(ob_arms.begin(), ob_arms.end(), ob_arm) - ob_arms.begin(); + if (index == 0) { + ob_arms.push_back(ob_arm); + } + + DEG_id_tag_update(&ob_arm->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + } } -Object *ArmatureImporter::create_armature_bones(Main *bmain, SkinInfo& skin) +Object *ArmatureImporter::create_armature_bones(Main *bmain, SkinInfo &skin) { - // just do like so: - // - get armature - // - enter editmode - // - add edit bones and head/tail properties using matrices and parent-child info - // - exit edit mode - // - set a sphere shape to leaf bones - - Object *ob_arm = NULL; - - /* - * find if there's another skin sharing at least one bone with this skin - * if so, use that skin's armature - */ - - /** - * Pseudocode: - * - * find_node_in_tree(node, root_joint) - * - * skin::find_root_joints(root_joints): - * std::vector root_joints; - * for each root in root_joints: - * for each joint in joints: - * if find_node_in_tree(joint, root): - * if (std::find(root_joints.begin(), root_joints.end(), root) == root_joints.end()) - * root_joints.push_back(root); - * - * for (each skin B with armature) { - * find all root joints for skin B - * - * for each joint X in skin A: - * for each root joint R in skin B: - * if (find_node_in_tree(X, R)) { - * shared = 1; - * goto endloop; - * } - * } - * - * endloop: - */ - - SkinInfo *a = &skin; - Object *shared = NULL; - std::vector<COLLADAFW::Node *> skin_root_joints; - std::vector<std::string> layer_labels; - - std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; - for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { - SkinInfo *b = &it->second; - if (b == a || b->BKE_armature_from_object() == NULL) - continue; - - skin_root_joints.clear(); - - b->find_root_joints(root_joints, joint_by_uid, skin_root_joints); - - std::vector<COLLADAFW::Node *>::iterator ri; - for (ri = skin_root_joints.begin(); ri != skin_root_joints.end(); ri++) { - if (a->uses_joint_or_descendant(*ri)) { - shared = b->BKE_armature_from_object(); - break; - } - } - - if (shared != NULL) - break; - } - - if (!shared && this->joint_parent_map.size() > 0) { - // All armatures have been created while creating the Node tree. - // The Collada exporter currently does not create a - // strict relationship between geometries and armatures - // So when we reimport a Blender collada file, then we have - // to guess what is meant. - // XXX This is not safe when we have more than one armatures - // in the import. - shared = this->joint_parent_map.begin()->second; - } - - if (shared) { - ob_arm = skin.set_armature(shared); - } - else { - ob_arm = skin.create_armature(m_bmain, scene, view_layer); //once for every armature - } - - // enter armature edit mode - bArmature *armature = (bArmature *)ob_arm->data; - ED_armature_to_edit(armature); - - totbone = 0; - // bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row - - // create bones - /* - TODO: - check if bones have already been created for a given joint - */ - - std::vector<COLLADAFW::Node *>::iterator ri; - for (ri = root_joints.begin(); ri != root_joints.end(); ri++) { - // for shared armature check if bone tree is already created - if (shared && std::find(skin_root_joints.begin(), skin_root_joints.end(), *ri) != skin_root_joints.end()) - continue; - - // since root_joints may contain joints for multiple controllers, we need to filter - if (skin.uses_joint_or_descendant(*ri)) { - - create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels); - - if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent()) - skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]); - } - } - - /* exit armature edit mode to populate the Armature object */ - ED_armature_from_edit(bmain, armature); - ED_armature_edit_free(armature); - - ED_armature_to_edit(armature); - if (this->import_settings->find_chains) { - connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); - } - fix_leaf_bone_hierarchy(armature, (Bone *)armature->bonebase.first, this->import_settings->fix_orientation); - ED_armature_from_edit(bmain, armature); - ED_armature_edit_free(armature); - - DEG_id_tag_update(&ob_arm->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - - return ob_arm; + // just do like so: + // - get armature + // - enter editmode + // - add edit bones and head/tail properties using matrices and parent-child info + // - exit edit mode + // - set a sphere shape to leaf bones + + Object *ob_arm = NULL; + + /* + * find if there's another skin sharing at least one bone with this skin + * if so, use that skin's armature + */ + + /** + * Pseudocode: + * + * find_node_in_tree(node, root_joint) + * + * skin::find_root_joints(root_joints): + * std::vector root_joints; + * for each root in root_joints: + * for each joint in joints: + * if find_node_in_tree(joint, root): + * if (std::find(root_joints.begin(), root_joints.end(), root) == root_joints.end()) + * root_joints.push_back(root); + * + * for (each skin B with armature) { + * find all root joints for skin B + * + * for each joint X in skin A: + * for each root joint R in skin B: + * if (find_node_in_tree(X, R)) { + * shared = 1; + * goto endloop; + * } + * } + * + * endloop: + */ + + SkinInfo *a = &skin; + Object *shared = NULL; + std::vector<COLLADAFW::Node *> skin_root_joints; + std::vector<std::string> layer_labels; + + std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; + for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { + SkinInfo *b = &it->second; + if (b == a || b->BKE_armature_from_object() == NULL) + continue; + + skin_root_joints.clear(); + + b->find_root_joints(root_joints, joint_by_uid, skin_root_joints); + + std::vector<COLLADAFW::Node *>::iterator ri; + for (ri = skin_root_joints.begin(); ri != skin_root_joints.end(); ri++) { + if (a->uses_joint_or_descendant(*ri)) { + shared = b->BKE_armature_from_object(); + break; + } + } + + if (shared != NULL) + break; + } + + if (!shared && this->joint_parent_map.size() > 0) { + // All armatures have been created while creating the Node tree. + // The Collada exporter currently does not create a + // strict relationship between geometries and armatures + // So when we reimport a Blender collada file, then we have + // to guess what is meant. + // XXX This is not safe when we have more than one armatures + // in the import. + shared = this->joint_parent_map.begin()->second; + } + + if (shared) { + ob_arm = skin.set_armature(shared); + } + else { + ob_arm = skin.create_armature(m_bmain, scene, view_layer); //once for every armature + } + + // enter armature edit mode + bArmature *armature = (bArmature *)ob_arm->data; + ED_armature_to_edit(armature); + + totbone = 0; + // bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row + + // create bones + /* + TODO: + check if bones have already been created for a given joint + */ + + std::vector<COLLADAFW::Node *>::iterator ri; + for (ri = root_joints.begin(); ri != root_joints.end(); ri++) { + // for shared armature check if bone tree is already created + if (shared && + std::find(skin_root_joints.begin(), skin_root_joints.end(), *ri) != skin_root_joints.end()) + continue; + + // since root_joints may contain joints for multiple controllers, we need to filter + if (skin.uses_joint_or_descendant(*ri)) { + + create_bone( + &skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels); + + if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && + !skin.get_parent()) + skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]); + } + } + + /* exit armature edit mode to populate the Armature object */ + ED_armature_from_edit(bmain, armature); + ED_armature_edit_free(armature); + + ED_armature_to_edit(armature); + if (this->import_settings->find_chains) { + connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); + } + fix_leaf_bone_hierarchy( + armature, (Bone *)armature->bonebase.first, this->import_settings->fix_orientation); + ED_armature_from_edit(bmain, armature); + ED_armature_edit_free(armature); + + DEG_id_tag_update(&ob_arm->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + + return ob_arm; } -void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]) +void ArmatureImporter::set_pose(Object *ob_arm, + COLLADAFW::Node *root_node, + const char *parentname, + float parent_mat[4][4]) { - const char *bone_name = bc_get_joint_name(root_node); - float mat[4][4]; - float obmat[4][4]; - - // object-space - get_node_mat(obmat, root_node, NULL, NULL); - - //if (*edbone) - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone_name); - //else fprintf ( "", - - // get world-space - if (parentname) { - mul_m4_m4m4(mat, parent_mat, obmat); - bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, parentname); - - mul_m4_m4m4(pchan->pose_mat, parchan->pose_mat, mat); - - } - else { - - copy_m4_m4(mat, obmat); - float invObmat[4][4]; - invert_m4_m4(invObmat, ob_arm->obmat); - mul_m4_m4m4(pchan->pose_mat, invObmat, mat); - - } - - //float angle = 0.0f; - ///*mat4_to_axis_angle(ax, &angle, mat); - //pchan->bone->roll = angle;*/ - - - COLLADAFW::NodePointerArray& children = root_node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { - set_pose(ob_arm, children[i], bone_name, mat); - } - + const char *bone_name = bc_get_joint_name(root_node); + float mat[4][4]; + float obmat[4][4]; + + // object-space + get_node_mat(obmat, root_node, NULL, NULL); + + //if (*edbone) + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone_name); + //else fprintf ( "", + + // get world-space + if (parentname) { + mul_m4_m4m4(mat, parent_mat, obmat); + bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, parentname); + + mul_m4_m4m4(pchan->pose_mat, parchan->pose_mat, mat); + } + else { + + copy_m4_m4(mat, obmat); + float invObmat[4][4]; + invert_m4_m4(invObmat, ob_arm->obmat); + mul_m4_m4m4(pchan->pose_mat, invObmat, mat); + } + + //float angle = 0.0f; + ///*mat4_to_axis_angle(ax, &angle, mat); + //pchan->bone->roll = angle;*/ + + COLLADAFW::NodePointerArray &children = root_node->getChildNodes(); + for (unsigned int i = 0; i < children.getCount(); i++) { + set_pose(ob_arm, children[i], bone_name, mat); + } } /** @@ -680,335 +700,344 @@ void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, con */ void ArmatureImporter::add_root_joint(COLLADAFW::Node *node, Object *parent) { - root_joints.push_back(node); - if (parent) { - joint_parent_map[node->getUniqueId()] = parent; - } + root_joints.push_back(node); + if (parent) { + joint_parent_map[node->getUniqueId()] = parent; + } } #if 0 void ArmatureImporter::add_root_joint(COLLADAFW::Node *node) { - // root_joints.push_back(node); - Object *ob_arm = find_armature(node); - if (ob_arm) { - get_armature_joints(ob_arm).root_joints.push_back(node); - } -#ifdef COLLADA_DEBUG - else { - fprintf(stderr, "%s cannot be added to armature.\n", get_joint_name(node)); - } -#endif + // root_joints.push_back(node); + Object *ob_arm = find_armature(node); + if (ob_arm) { + get_armature_joints(ob_arm).root_joints.push_back(node); + } +# ifdef COLLADA_DEBUG + else { + fprintf(stderr, "%s cannot be added to armature.\n", get_joint_name(node)); + } +# endif } #endif // here we add bones to armatures, having armatures previously created in write_controller void ArmatureImporter::make_armatures(bContext *C, std::vector<Object *> &objects_to_scale) { - Main *bmain = CTX_data_main(C); - std::vector<Object *> ob_arms; - std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; + Main *bmain = CTX_data_main(C); + std::vector<Object *> ob_arms; + std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; - leaf_bone_length = FLT_MAX; /*TODO: Make this work for more than one armature in the import file*/ + leaf_bone_length = + FLT_MAX; /*TODO: Make this work for more than one armature in the import file*/ - for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { + for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { - SkinInfo& skin = it->second; + SkinInfo &skin = it->second; - Object *ob_arm = create_armature_bones(bmain, skin); + Object *ob_arm = create_armature_bones(bmain, skin); - // link armature with a mesh object - const COLLADAFW::UniqueId &uid = skin.get_controller_uid(); - const COLLADAFW::UniqueId *guid = get_geometry_uid(uid); - if (guid != NULL) { - Object *ob = mesh_importer->get_object_by_geom_uid(*guid); - if (ob) { - skin.link_armature(C, ob, joint_by_uid, this); + // link armature with a mesh object + const COLLADAFW::UniqueId &uid = skin.get_controller_uid(); + const COLLADAFW::UniqueId *guid = get_geometry_uid(uid); + if (guid != NULL) { + Object *ob = mesh_importer->get_object_by_geom_uid(*guid); + if (ob) { + skin.link_armature(C, ob, joint_by_uid, this); - std::vector<Object *>::iterator ob_it = std::find(objects_to_scale.begin(), objects_to_scale.end(), ob); + std::vector<Object *>::iterator ob_it = std::find( + objects_to_scale.begin(), objects_to_scale.end(), ob); - if (ob_it != objects_to_scale.end()) { - int index = ob_it - objects_to_scale.begin(); - objects_to_scale.erase(objects_to_scale.begin() + index); - } + if (ob_it != objects_to_scale.end()) { + int index = ob_it - objects_to_scale.begin(); + objects_to_scale.erase(objects_to_scale.begin() + index); + } - if (std::find(objects_to_scale.begin(), objects_to_scale.end(), ob_arm) == objects_to_scale.end()) { - objects_to_scale.push_back(ob_arm); - } + if (std::find(objects_to_scale.begin(), objects_to_scale.end(), ob_arm) == + objects_to_scale.end()) { + objects_to_scale.push_back(ob_arm); + } - if (std::find(ob_arms.begin(), ob_arms.end(), ob_arm) == ob_arms.end()) { - ob_arms.push_back(ob_arm); - } - } - else - fprintf(stderr, "Cannot find object to link armature with.\n"); - } - else - fprintf(stderr, "Cannot find geometry to link armature with.\n"); + if (std::find(ob_arms.begin(), ob_arms.end(), ob_arm) == ob_arms.end()) { + ob_arms.push_back(ob_arm); + } + } + else + fprintf(stderr, "Cannot find object to link armature with.\n"); + } + else + fprintf(stderr, "Cannot find geometry to link armature with.\n"); - // set armature parent if any - Object *par = skin.get_parent(); - if (par) - bc_set_parent(skin.BKE_armature_from_object(), par, C, false); + // set armature parent if any + Object *par = skin.get_parent(); + if (par) + bc_set_parent(skin.BKE_armature_from_object(), par, C, false); - // free memory stolen from SkinControllerData - skin.free(); - } + // free memory stolen from SkinControllerData + skin.free(); + } - //for bones without skins - create_armature_bones(bmain, ob_arms); + //for bones without skins + create_armature_bones(bmain, ob_arms); - // Fix bone relations - std::vector<Object *>::iterator ob_arm_it; - for (ob_arm_it = ob_arms.begin(); ob_arm_it != ob_arms.end(); ob_arm_it++) { + // Fix bone relations + std::vector<Object *>::iterator ob_arm_it; + for (ob_arm_it = ob_arms.begin(); ob_arm_it != ob_arms.end(); ob_arm_it++) { - Object *ob_arm = *ob_arm_it; - bArmature *armature = (bArmature *)ob_arm->data; + Object *ob_arm = *ob_arm_it; + bArmature *armature = (bArmature *)ob_arm->data; - /* and step back to edit mode to fix the leaf nodes */ - ED_armature_to_edit(armature); + /* and step back to edit mode to fix the leaf nodes */ + ED_armature_to_edit(armature); - fix_parent_connect(armature, (Bone *)armature->bonebase.first); + fix_parent_connect(armature, (Bone *)armature->bonebase.first); - ED_armature_from_edit(bmain, armature); - ED_armature_edit_free(armature); - } + ED_armature_from_edit(bmain, armature); + ED_armature_edit_free(armature); + } } #if 0 // link with meshes, create vertex groups, assign weights void ArmatureImporter::link_armature(Object *ob_arm, const COLLADAFW::UniqueId& geom_id, const COLLADAFW::UniqueId& controller_data_id) { - Object *ob = mesh_importer->get_object_by_geom_uid(geom_id); + Object *ob = mesh_importer->get_object_by_geom_uid(geom_id); - if (!ob) { - fprintf(stderr, "Cannot find object by geometry UID.\n"); - return; - } + if (!ob) { + fprintf(stderr, "Cannot find object by geometry UID.\n"); + return; + } - if (skin_by_data_uid.find(controller_data_id) == skin_by_data_uid.end()) { - fprintf(stderr, "Cannot find skin info by controller data UID.\n"); - return; - } + if (skin_by_data_uid.find(controller_data_id) == skin_by_data_uid.end()) { + fprintf(stderr, "Cannot find skin info by controller data UID.\n"); + return; + } - SkinInfo& skin = skin_by_data_uid[conroller_data_id]; + SkinInfo& skin = skin_by_data_uid[conroller_data_id]; - // create vertex groups + // create vertex groups } #endif bool ArmatureImporter::write_skin_controller_data(const COLLADAFW::SkinControllerData *data) { - // at this stage we get vertex influence info that should go into me->verts and ob->defbase - // there's no info to which object this should be long so we associate it with skin controller data UID + // at this stage we get vertex influence info that should go into me->verts and ob->defbase + // there's no info to which object this should be long so we associate it with skin controller data UID - // don't forget to call defgroup_unique_name before we copy + // don't forget to call defgroup_unique_name before we copy - // controller data uid -> [armature] -> joint data, - // [mesh object] - // + // controller data uid -> [armature] -> joint data, + // [mesh object] + // - SkinInfo skin(unit_converter); - skin.borrow_skin_controller_data(data); + SkinInfo skin(unit_converter); + skin.borrow_skin_controller_data(data); - // store join inv bind matrix to use it later in armature construction - const COLLADAFW::Matrix4Array& inv_bind_mats = data->getInverseBindMatrices(); - for (unsigned int i = 0; i < data->getJointsCount(); i++) { - skin.add_joint(inv_bind_mats[i]); - } + // store join inv bind matrix to use it later in armature construction + const COLLADAFW::Matrix4Array &inv_bind_mats = data->getInverseBindMatrices(); + for (unsigned int i = 0; i < data->getJointsCount(); i++) { + skin.add_joint(inv_bind_mats[i]); + } - skin_by_data_uid[data->getUniqueId()] = skin; + skin_by_data_uid[data->getUniqueId()] = skin; - return true; + return true; } bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller) { - // - create and store armature object - const COLLADAFW::UniqueId& con_id = controller->getUniqueId(); - - if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) { - COLLADAFW::SkinController *co = (COLLADAFW::SkinController *)controller; - // to be able to find geom id by controller id - geom_uid_by_controller_uid[con_id] = co->getSource(); - - const COLLADAFW::UniqueId& data_uid = co->getSkinControllerData(); - if (skin_by_data_uid.find(data_uid) == skin_by_data_uid.end()) { - fprintf(stderr, "Cannot find skin by controller data UID.\n"); - return true; - } - - skin_by_data_uid[data_uid].set_controller(co); - } - // morph controller - else if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_MORPH) { - COLLADAFW::MorphController *co = (COLLADAFW::MorphController *)controller; - // to be able to find geom id by controller id - geom_uid_by_controller_uid[con_id] = co->getSource(); - //Shape keys are applied in DocumentImporter->finish() - morph_controllers.push_back(co); - } - - return true; + // - create and store armature object + const COLLADAFW::UniqueId &con_id = controller->getUniqueId(); + + if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) { + COLLADAFW::SkinController *co = (COLLADAFW::SkinController *)controller; + // to be able to find geom id by controller id + geom_uid_by_controller_uid[con_id] = co->getSource(); + + const COLLADAFW::UniqueId &data_uid = co->getSkinControllerData(); + if (skin_by_data_uid.find(data_uid) == skin_by_data_uid.end()) { + fprintf(stderr, "Cannot find skin by controller data UID.\n"); + return true; + } + + skin_by_data_uid[data_uid].set_controller(co); + } + // morph controller + else if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_MORPH) { + COLLADAFW::MorphController *co = (COLLADAFW::MorphController *)controller; + // to be able to find geom id by controller id + geom_uid_by_controller_uid[con_id] = co->getSource(); + //Shape keys are applied in DocumentImporter->finish() + morph_controllers.push_back(co); + } + + return true; } void ArmatureImporter::make_shape_keys(bContext *C) { - Main *bmain = CTX_data_main(C); - std::vector<COLLADAFW::MorphController *>::iterator mc; - float weight; - - for (mc = morph_controllers.begin(); mc != morph_controllers.end(); mc++) { - //Controller data - COLLADAFW::UniqueIdArray& morphTargetIds = (*mc)->getMorphTargets(); - COLLADAFW::FloatOrDoubleArray& morphWeights = (*mc)->getMorphWeights(); - - //Prereq: all the geometries must be imported and mesh objects must be made - Object *source_ob = this->mesh_importer->get_object_by_geom_uid((*mc)->getSource()); - - if (source_ob) { - - Mesh *source_me = (Mesh *)source_ob->data; - //insert key to source mesh - Key *key = source_me->key = BKE_key_add(bmain, (ID *)source_me); - key->type = KEY_RELATIVE; - KeyBlock *kb; - - //insert basis key - kb = BKE_keyblock_add_ctime(key, "Basis", false); - BKE_keyblock_convert_from_mesh(source_me, key, kb); - - //insert other shape keys - for (int i = 0 ; i < morphTargetIds.getCount() ; i++ ) { - //better to have a separate map of morph objects, - //This'll do for now since only mesh morphing is imported - - Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]); - - if (me) { - me->key = key; - std::string morph_name = *this->mesh_importer->get_geometry_name(me->id.name); - - kb = BKE_keyblock_add_ctime(key, morph_name.c_str(), false); - BKE_keyblock_convert_from_mesh(me, key, kb); - - //apply weights - weight = morphWeights.getFloatValues()->getData()[i]; - kb->curval = weight; - } - else { - fprintf(stderr, "Morph target geometry not found.\n"); - } - } - } - else { - fprintf(stderr, "Morph target object not found.\n"); - } - } + Main *bmain = CTX_data_main(C); + std::vector<COLLADAFW::MorphController *>::iterator mc; + float weight; + + for (mc = morph_controllers.begin(); mc != morph_controllers.end(); mc++) { + //Controller data + COLLADAFW::UniqueIdArray &morphTargetIds = (*mc)->getMorphTargets(); + COLLADAFW::FloatOrDoubleArray &morphWeights = (*mc)->getMorphWeights(); + + //Prereq: all the geometries must be imported and mesh objects must be made + Object *source_ob = this->mesh_importer->get_object_by_geom_uid((*mc)->getSource()); + + if (source_ob) { + + Mesh *source_me = (Mesh *)source_ob->data; + //insert key to source mesh + Key *key = source_me->key = BKE_key_add(bmain, (ID *)source_me); + key->type = KEY_RELATIVE; + KeyBlock *kb; + + //insert basis key + kb = BKE_keyblock_add_ctime(key, "Basis", false); + BKE_keyblock_convert_from_mesh(source_me, key, kb); + + //insert other shape keys + for (int i = 0; i < morphTargetIds.getCount(); i++) { + //better to have a separate map of morph objects, + //This'll do for now since only mesh morphing is imported + + Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]); + + if (me) { + me->key = key; + std::string morph_name = *this->mesh_importer->get_geometry_name(me->id.name); + + kb = BKE_keyblock_add_ctime(key, morph_name.c_str(), false); + BKE_keyblock_convert_from_mesh(me, key, kb); + + //apply weights + weight = morphWeights.getFloatValues()->getData()[i]; + kb->curval = weight; + } + else { + fprintf(stderr, "Morph target geometry not found.\n"); + } + } + } + else { + fprintf(stderr, "Morph target object not found.\n"); + } + } } - -COLLADAFW::UniqueId *ArmatureImporter::get_geometry_uid(const COLLADAFW::UniqueId& controller_uid) +COLLADAFW::UniqueId *ArmatureImporter::get_geometry_uid(const COLLADAFW::UniqueId &controller_uid) { - if (geom_uid_by_controller_uid.find(controller_uid) == geom_uid_by_controller_uid.end()) - return NULL; + if (geom_uid_by_controller_uid.find(controller_uid) == geom_uid_by_controller_uid.end()) + return NULL; - return &geom_uid_by_controller_uid[controller_uid]; + return &geom_uid_by_controller_uid[controller_uid]; } Object *ArmatureImporter::get_armature_for_joint(COLLADAFW::Node *node) { - std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; - for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { - SkinInfo& skin = it->second; - - if (skin.uses_joint_or_descendant(node)) - return skin.BKE_armature_from_object(); - } - - std::map<COLLADAFW::UniqueId, Object *>::iterator arm; - for (arm = unskinned_armature_map.begin(); arm != unskinned_armature_map.end(); arm++) { - if (arm->first == node->getUniqueId() ) - return arm->second; - } - return NULL; + std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; + for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { + SkinInfo &skin = it->second; + + if (skin.uses_joint_or_descendant(node)) + return skin.BKE_armature_from_object(); + } + + std::map<COLLADAFW::UniqueId, Object *>::iterator arm; + for (arm = unskinned_armature_map.begin(); arm != unskinned_armature_map.end(); arm++) { + if (arm->first == node->getUniqueId()) + return arm->second; + } + return NULL; } -void ArmatureImporter::set_tags_map(TagsMap & tagsMap) +void ArmatureImporter::set_tags_map(TagsMap &tagsMap) { - this->uid_tags_map = tagsMap; + this->uid_tags_map = tagsMap; } -void ArmatureImporter::get_rna_path_for_joint(COLLADAFW::Node *node, char *joint_path, size_t count) +void ArmatureImporter::get_rna_path_for_joint(COLLADAFW::Node *node, + char *joint_path, + size_t count) { - BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", bc_get_joint_name(node)); + BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", bc_get_joint_name(node)); } // gives a world-space mat bool ArmatureImporter::get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint) { - std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; - bool found = false; - for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { - SkinInfo& skin = it->second; - if ((found = skin.get_joint_inv_bind_matrix(m, joint))) { - invert_m4(m); - break; - } - } - - return found; + std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it; + bool found = false; + for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) { + SkinInfo &skin = it->second; + if ((found = skin.get_joint_inv_bind_matrix(m, joint))) { + invert_m4(m); + break; + } + } + + return found; } -BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node, int sibcount, std::vector<std::string> &layer_labels, BoneExtensionMap &extended_bones) +BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, + COLLADAFW::Node *node, + int sibcount, + std::vector<std::string> &layer_labels, + BoneExtensionMap &extended_bones) { - BoneExtended *be = new BoneExtended(bone); - extended_bones[bone->name] = be; + BoneExtended *be = new BoneExtended(bone); + extended_bones[bone->name] = be; - TagsMap::iterator etit; - ExtraTags *et = 0; - etit = uid_tags_map.find(node->getUniqueId().toAscii()); + TagsMap::iterator etit; + ExtraTags *et = 0; + etit = uid_tags_map.find(node->getUniqueId().toAscii()); - bool has_connect = false; - int connect_type = -1; + bool has_connect = false; + int connect_type = -1; - if (etit != uid_tags_map.end()) { + if (etit != uid_tags_map.end()) { - float tail[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; - float roll = 0; - std::string layers; + float tail[3] = {FLT_MAX, FLT_MAX, FLT_MAX}; + float roll = 0; + std::string layers; - et = etit->second; + et = etit->second; - bool has_tail = false; - has_tail |= et->setData("tip_x", &tail[0]); - has_tail |= et->setData("tip_y", &tail[1]); - has_tail |= et->setData("tip_z", &tail[2]); + bool has_tail = false; + has_tail |= et->setData("tip_x", &tail[0]); + has_tail |= et->setData("tip_y", &tail[1]); + has_tail |= et->setData("tip_z", &tail[2]); - has_connect = et->setData("connect", &connect_type); - bool has_roll = et->setData("roll", &roll); + has_connect = et->setData("connect", &connect_type); + bool has_roll = et->setData("roll", &roll); - layers = et->setData("layer", layers); + layers = et->setData("layer", layers); - if (has_tail && !has_connect) - { - /* got a bone tail definition but no connect info -> bone is not connected */ - has_connect = true; - connect_type = 0; - } + if (has_tail && !has_connect) { + /* got a bone tail definition but no connect info -> bone is not connected */ + has_connect = true; + connect_type = 0; + } - be->set_bone_layers(layers, layer_labels); - if (has_tail) be->set_tail(tail); - if (has_roll) be->set_roll(roll); - } + be->set_bone_layers(layers, layer_labels); + if (has_tail) + be->set_tail(tail); + if (has_roll) + be->set_roll(roll); + } - if (!has_connect && this->import_settings->auto_connect) { - /* auto connect only whyen parent has exactly one child*/ - connect_type = sibcount == 1; - } + if (!has_connect && this->import_settings->auto_connect) { + /* auto connect only whyen parent has exactly one child*/ + connect_type = sibcount == 1; + } - be->set_use_connect(connect_type); - be->set_leaf_bone(true); + be->set_use_connect(connect_type); + be->set_leaf_bone(true); - return *be; + return *be; } diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h index 4c82b1e55e3..cfcd9501790 100644 --- a/source/blender/collada/ArmatureImporter.h +++ b/source/blender/collada/ArmatureImporter.h @@ -53,118 +53,131 @@ extern "C" { #define UNLIMITED_CHAIN_MAX INT_MAX #define MINIMUM_BONE_LENGTH 0.000001f -class ArmatureImporter : private TransformReader -{ -private: - Main *m_bmain; - Scene *scene; - ViewLayer *view_layer; - UnitConverter *unit_converter; - const ImportSettings *import_settings; - - // std::map<int, JointData> joint_index_to_joint_info_map; - // std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map; - BoneExtensionManager bone_extension_manager; - // int bone_direction_row; // XXX not used - float leaf_bone_length; - int totbone; - // XXX not used - // float min_angle; // minimum angle between bone head-tail and a row of bone matrix +class ArmatureImporter : private TransformReader { + private: + Main *m_bmain; + Scene *scene; + ViewLayer *view_layer; + UnitConverter *unit_converter; + const ImportSettings *import_settings; + + // std::map<int, JointData> joint_index_to_joint_info_map; + // std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map; + BoneExtensionManager bone_extension_manager; + // int bone_direction_row; // XXX not used + float leaf_bone_length; + int totbone; + // XXX not used + // float min_angle; // minimum angle between bone head-tail and a row of bone matrix #if 0 - struct ArmatureJoints { - Object *ob_arm; - std::vector<COLLADAFW::Node*> root_joints; - }; - std::vector<ArmatureJoints> armature_joints; + struct ArmatureJoints { + Object *ob_arm; + std::vector<COLLADAFW::Node*> root_joints; + }; + std::vector<ArmatureJoints> armature_joints; #endif - Object *empty; // empty for leaf bones + Object *empty; // empty for leaf bones - std::map<COLLADAFW::UniqueId, COLLADAFW::UniqueId> geom_uid_by_controller_uid; - std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> joint_by_uid; // contains all joints - std::vector<COLLADAFW::Node*> root_joints; - std::vector<COLLADAFW::Node*> finished_joints; - std::vector<COLLADAFW::MorphController*> morph_controllers; - std::map<COLLADAFW::UniqueId, Object*> joint_parent_map; - std::map<COLLADAFW::UniqueId, Object*> unskinned_armature_map; + std::map<COLLADAFW::UniqueId, COLLADAFW::UniqueId> geom_uid_by_controller_uid; + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> joint_by_uid; // contains all joints + std::vector<COLLADAFW::Node *> root_joints; + std::vector<COLLADAFW::Node *> finished_joints; + std::vector<COLLADAFW::MorphController *> morph_controllers; + std::map<COLLADAFW::UniqueId, Object *> joint_parent_map; + std::map<COLLADAFW::UniqueId, Object *> unskinned_armature_map; - MeshImporterBase *mesh_importer; + MeshImporterBase *mesh_importer; - // This is used to store data passed in write_controller_data. - // Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members - // so that arrays don't get freed until we free them explicitly. + // This is used to store data passed in write_controller_data. + // Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members + // so that arrays don't get freed until we free them explicitly. - std::map<COLLADAFW::UniqueId, SkinInfo> skin_by_data_uid; // data UID = skin controller data UID + std::map<COLLADAFW::UniqueId, SkinInfo> skin_by_data_uid; // data UID = skin controller data UID #if 0 - JointData *get_joint_data(COLLADAFW::Node *node); + JointData *get_joint_data(COLLADAFW::Node *node); #endif - int create_bone( - SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild, - float parent_mat[4][4], bArmature *arm, std::vector<std::string> &layer_labels); - - BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node, int sibcount, std::vector<std::string> &layer_labels, BoneExtensionMap &extended_bones); - - void fix_leaf_bone_hierarchy(bArmature *armature, Bone *bone, bool fix_orientation); - void fix_leaf_bone(bArmature *armature, EditBone *ebone, BoneExtended *be, bool fix_orientation); - void fix_parent_connect(bArmature *armature, Bone *bone); - void connect_bone_chains(bArmature *armature, Bone *bone, const int max_chain_length); - - void set_pose( Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]); + int create_bone(SkinInfo *skin, + COLLADAFW::Node *node, + EditBone *parent, + int totchild, + float parent_mat[4][4], + bArmature *arm, + std::vector<std::string> &layer_labels); + + BoneExtended &add_bone_extended(EditBone *bone, + COLLADAFW::Node *node, + int sibcount, + std::vector<std::string> &layer_labels, + BoneExtensionMap &extended_bones); + + void fix_leaf_bone_hierarchy(bArmature *armature, Bone *bone, bool fix_orientation); + void fix_leaf_bone(bArmature *armature, EditBone *ebone, BoneExtended *be, bool fix_orientation); + void fix_parent_connect(bArmature *armature, Bone *bone); + void connect_bone_chains(bArmature *armature, Bone *bone, const int max_chain_length); + + void set_pose(Object *ob_arm, + COLLADAFW::Node *root_node, + const char *parentname, + float parent_mat[4][4]); #if 0 - void set_leaf_bone_shapes(Object *ob_arm); - void set_euler_rotmode(); + void set_leaf_bone_shapes(Object *ob_arm); + void set_euler_rotmode(); #endif - Object *get_empty_for_leaves(); + Object *get_empty_for_leaves(); #if 0 - Object *find_armature(COLLADAFW::Node *node); + Object *find_armature(COLLADAFW::Node *node); - ArmatureJoints& get_armature_joints(Object *ob_arm); + ArmatureJoints& get_armature_joints(Object *ob_arm); #endif - Object *create_armature_bones(Main *bmain, SkinInfo& skin); - void create_armature_bones(Main *bmain, std::vector<Object *> &arm_objs); + Object *create_armature_bones(Main *bmain, SkinInfo &skin); + void create_armature_bones(Main *bmain, std::vector<Object *> &arm_objs); - /** TagsMap typedef for uid_tags_map. */ - typedef std::map<std::string, ExtraTags*> TagsMap; - TagsMap uid_tags_map; -public: + /** TagsMap typedef for uid_tags_map. */ + typedef std::map<std::string, ExtraTags *> TagsMap; + TagsMap uid_tags_map; - ArmatureImporter( - UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings); - ~ArmatureImporter(); + public: + ArmatureImporter(UnitConverter *conv, + MeshImporterBase *mesh, + Main *bmain, + Scene *sce, + ViewLayer *view_layer, + const ImportSettings *import_settings); + ~ArmatureImporter(); - void add_root_joint(COLLADAFW::Node *node, Object *parent); + void add_root_joint(COLLADAFW::Node *node, Object *parent); - // here we add bones to armatures, having armatures previously created in write_controller - void make_armatures(bContext *C, std::vector<Object *> &objects_to_scale); + // here we add bones to armatures, having armatures previously created in write_controller + void make_armatures(bContext *C, std::vector<Object *> &objects_to_scale); - void make_shape_keys(bContext *C); + void make_shape_keys(bContext *C); #if 0 - // link with meshes, create vertex groups, assign weights - void link_armature(Object *ob_arm, const COLLADAFW::UniqueId& geom_id, const COLLADAFW::UniqueId& controller_data_id); + // link with meshes, create vertex groups, assign weights + void link_armature(Object *ob_arm, const COLLADAFW::UniqueId& geom_id, const COLLADAFW::UniqueId& controller_data_id); #endif - bool write_skin_controller_data(const COLLADAFW::SkinControllerData* data); - - bool write_controller(const COLLADAFW::Controller* controller); + bool write_skin_controller_data(const COLLADAFW::SkinControllerData *data); - COLLADAFW::UniqueId *get_geometry_uid(const COLLADAFW::UniqueId& controller_uid); + bool write_controller(const COLLADAFW::Controller *controller); - Object *get_armature_for_joint(COLLADAFW::Node *node); + COLLADAFW::UniqueId *get_geometry_uid(const COLLADAFW::UniqueId &controller_uid); - void get_rna_path_for_joint(COLLADAFW::Node *node, char *joint_path, size_t count); + Object *get_armature_for_joint(COLLADAFW::Node *node); - // gives a world-space mat - bool get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint); + void get_rna_path_for_joint(COLLADAFW::Node *node, char *joint_path, size_t count); - void set_tags_map( TagsMap& tags_map); + // gives a world-space mat + bool get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint); + void set_tags_map(TagsMap &tags_map); }; #endif diff --git a/source/blender/collada/BCAnimationCurve.cpp b/source/blender/collada/BCAnimationCurve.cpp index 064f3254b11..2eb30d6779c 100644 --- a/source/blender/collada/BCAnimationCurve.cpp +++ b/source/blender/collada/BCAnimationCurve.cpp @@ -21,652 +21,631 @@ BCAnimationCurve::BCAnimationCurve() { - this->curve_key.set_object_type(BC_ANIMATION_TYPE_OBJECT); - this->fcurve = NULL; - this->curve_is_local_copy = false; + this->curve_key.set_object_type(BC_ANIMATION_TYPE_OBJECT); + this->fcurve = NULL; + this->curve_is_local_copy = false; } BCAnimationCurve::BCAnimationCurve(const BCAnimationCurve &other) { - this->min = other.min; - this->max = other.max; - this->fcurve = other.fcurve; - this->curve_key = other.curve_key; - this->curve_is_local_copy = false; - this->id_ptr = other.id_ptr; + this->min = other.min; + this->max = other.max; + this->fcurve = other.fcurve; + this->curve_key = other.curve_key; + this->curve_is_local_copy = false; + this->id_ptr = other.id_ptr; - /* The fcurve of the new instance is a copy and can be modified */ + /* The fcurve of the new instance is a copy and can be modified */ - get_edit_fcurve(); + get_edit_fcurve(); } BCAnimationCurve::BCAnimationCurve(BCCurveKey key, Object *ob, FCurve *fcu) { - this->min = 0; - this->max = 0; - this->curve_key = key; - this->fcurve = fcu; - this->curve_is_local_copy = false; - init_pointer_rna(ob); + this->min = 0; + this->max = 0; + this->curve_key = key; + this->fcurve = fcu; + this->curve_is_local_copy = false; + init_pointer_rna(ob); } BCAnimationCurve::BCAnimationCurve(const BCCurveKey &key, Object *ob) { - this->curve_key = key; - this->fcurve = NULL; - this->curve_is_local_copy = false; - init_pointer_rna(ob); + this->curve_key = key; + this->fcurve = NULL; + this->curve_is_local_copy = false; + init_pointer_rna(ob); } void BCAnimationCurve::init_pointer_rna(Object *ob) { - switch (this->curve_key.get_animation_type()) { - case BC_ANIMATION_TYPE_BONE: - { - bArmature *arm = (bArmature *)ob->data; - RNA_id_pointer_create(&arm->id, &id_ptr); - } - break; - case BC_ANIMATION_TYPE_OBJECT: - { - RNA_id_pointer_create(&ob->id, &id_ptr); - } - break; - case BC_ANIMATION_TYPE_MATERIAL: - { - Material *ma = give_current_material(ob, curve_key.get_subindex() + 1); - RNA_id_pointer_create(&ma->id, &id_ptr); - } - break; - case BC_ANIMATION_TYPE_CAMERA: - { - Camera *camera = (Camera *)ob->data; - RNA_id_pointer_create(&camera->id, &id_ptr); - } - break; - case BC_ANIMATION_TYPE_LIGHT: - { - Light *lamp = (Light *)ob->data; - RNA_id_pointer_create(&lamp->id, &id_ptr); - } - break; - default: - fprintf(stderr, "BC_animation_curve_type %d not supported", this->curve_key.get_array_index()); - break; - } + switch (this->curve_key.get_animation_type()) { + case BC_ANIMATION_TYPE_BONE: { + bArmature *arm = (bArmature *)ob->data; + RNA_id_pointer_create(&arm->id, &id_ptr); + } break; + case BC_ANIMATION_TYPE_OBJECT: { + RNA_id_pointer_create(&ob->id, &id_ptr); + } break; + case BC_ANIMATION_TYPE_MATERIAL: { + Material *ma = give_current_material(ob, curve_key.get_subindex() + 1); + RNA_id_pointer_create(&ma->id, &id_ptr); + } break; + case BC_ANIMATION_TYPE_CAMERA: { + Camera *camera = (Camera *)ob->data; + RNA_id_pointer_create(&camera->id, &id_ptr); + } break; + case BC_ANIMATION_TYPE_LIGHT: { + Light *lamp = (Light *)ob->data; + RNA_id_pointer_create(&lamp->id, &id_ptr); + } break; + default: + fprintf( + stderr, "BC_animation_curve_type %d not supported", this->curve_key.get_array_index()); + break; + } } void BCAnimationCurve::delete_fcurve(FCurve *fcu) { - free_fcurve(fcu); + free_fcurve(fcu); } FCurve *BCAnimationCurve::create_fcurve(int array_index, const char *rna_path) { - FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve"); - fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED); - fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); - fcu->array_index = array_index; - return fcu; + FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve"); + fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED); + fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); + fcu->array_index = array_index; + return fcu; } void BCAnimationCurve::create_bezt(float frame, float output) { - FCurve *fcu = get_edit_fcurve(); - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - bez.vec[1][0] = frame; - bez.vec[1][1] = output; - bez.ipo = U.ipo_new; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); - calchandles_fcurve(fcu); + FCurve *fcu = get_edit_fcurve(); + BezTriple bez; + memset(&bez, 0, sizeof(BezTriple)); + bez.vec[1][0] = frame; + bez.vec[1][1] = output; + bez.ipo = U.ipo_new; /* use default interpolation mode here... */ + bez.f1 = bez.f2 = bez.f3 = SELECT; + bez.h1 = bez.h2 = HD_AUTO; + insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); + calchandles_fcurve(fcu); } BCAnimationCurve::~BCAnimationCurve() { - if (curve_is_local_copy && fcurve) { - //fprintf(stderr, "removed fcurve %s\n", fcurve->rna_path); - delete_fcurve(fcurve); - this->fcurve = NULL; - } + if (curve_is_local_copy && fcurve) { + //fprintf(stderr, "removed fcurve %s\n", fcurve->rna_path); + delete_fcurve(fcurve); + this->fcurve = NULL; + } } const bool BCAnimationCurve::is_of_animation_type(BC_animation_type type) const { - return curve_key.get_animation_type() == type; + return curve_key.get_animation_type() == type; } const std::string BCAnimationCurve::get_channel_target() const { - const std::string path = curve_key.get_path(); - return bc_string_after(path, '.'); + const std::string path = curve_key.get_path(); + return bc_string_after(path, '.'); } const std::string BCAnimationCurve::get_animation_name(Object *ob) const { - std::string name; - - switch (curve_key.get_animation_type()) { - case BC_ANIMATION_TYPE_OBJECT: - { - name = id_name(ob); - } - break; - - case BC_ANIMATION_TYPE_BONE: - { - if (fcurve == NULL || fcurve->rna_path == NULL) - name = ""; - else { - const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones["); - name = (boneName) ? std::string(boneName) : ""; - } - } - break; - - case BC_ANIMATION_TYPE_CAMERA: - { - Camera *camera = (Camera *)ob->data; - name = id_name(ob) + "-" + id_name(camera) + "-camera"; - } - break; - - case BC_ANIMATION_TYPE_LIGHT: - { - Light *lamp = (Light *)ob->data; - name = id_name(ob) + "-" + id_name(lamp) + "-light"; - } - break; - - case BC_ANIMATION_TYPE_MATERIAL: - { - Material *ma = give_current_material(ob, this->curve_key.get_subindex() + 1); - name = id_name(ob) + "-" + id_name(ma) + "-material"; - } - break; - - default: - { - name = ""; - } - } - - return name; + std::string name; + + switch (curve_key.get_animation_type()) { + case BC_ANIMATION_TYPE_OBJECT: { + name = id_name(ob); + } break; + + case BC_ANIMATION_TYPE_BONE: { + if (fcurve == NULL || fcurve->rna_path == NULL) + name = ""; + else { + const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones["); + name = (boneName) ? std::string(boneName) : ""; + } + } break; + + case BC_ANIMATION_TYPE_CAMERA: { + Camera *camera = (Camera *)ob->data; + name = id_name(ob) + "-" + id_name(camera) + "-camera"; + } break; + + case BC_ANIMATION_TYPE_LIGHT: { + Light *lamp = (Light *)ob->data; + name = id_name(ob) + "-" + id_name(lamp) + "-light"; + } break; + + case BC_ANIMATION_TYPE_MATERIAL: { + Material *ma = give_current_material(ob, this->curve_key.get_subindex() + 1); + name = id_name(ob) + "-" + id_name(ma) + "-material"; + } break; + + default: { + name = ""; + } + } + + return name; } const int BCAnimationCurve::get_channel_index() const { - return curve_key.get_array_index(); + return curve_key.get_array_index(); } const int BCAnimationCurve::get_subindex() const { - return curve_key.get_subindex(); + return curve_key.get_subindex(); } const std::string BCAnimationCurve::get_rna_path() const { - return curve_key.get_path(); + return curve_key.get_path(); } const int BCAnimationCurve::sample_count() const { - if (fcurve == NULL) - return 0; - return fcurve->totvert; + if (fcurve == NULL) + return 0; + return fcurve->totvert; } const int BCAnimationCurve::closest_index_above(const float sample_frame, const int start_at) const { - if (fcurve == NULL) - return -1; + if (fcurve == NULL) + return -1; - const int cframe = fcurve->bezt[start_at].vec[1][0]; // inacurate! + const int cframe = fcurve->bezt[start_at].vec[1][0]; // inacurate! - if (fabs(cframe - sample_frame) < 0.00001) - return start_at; - return (fcurve->totvert > start_at + 1) ? start_at + 1 : start_at; + if (fabs(cframe - sample_frame) < 0.00001) + return start_at; + return (fcurve->totvert > start_at + 1) ? start_at + 1 : start_at; } const int BCAnimationCurve::closest_index_below(const float sample_frame) const { - if (fcurve == NULL) - return -1; + if (fcurve == NULL) + return -1; - float lower_frame = sample_frame; - float upper_frame = sample_frame; - int lower_index = 0; - int upper_index = 0; + float lower_frame = sample_frame; + float upper_frame = sample_frame; + int lower_index = 0; + int upper_index = 0; - for (int fcu_index = 0; fcu_index < fcurve->totvert; ++fcu_index) { - upper_index = fcu_index; + for (int fcu_index = 0; fcu_index < fcurve->totvert; ++fcu_index) { + upper_index = fcu_index; - const int cframe = fcurve->bezt[fcu_index].vec[1][0]; // inacurate! - if (cframe <= sample_frame) { - lower_frame = cframe; - lower_index = fcu_index; - } - if (cframe >= sample_frame) { - upper_frame = cframe; - break; - } - } + const int cframe = fcurve->bezt[fcu_index].vec[1][0]; // inacurate! + if (cframe <= sample_frame) { + lower_frame = cframe; + lower_index = fcu_index; + } + if (cframe >= sample_frame) { + upper_frame = cframe; + break; + } + } - if (lower_index == upper_index) - return lower_index; + if (lower_index == upper_index) + return lower_index; - const float fraction = float(sample_frame - lower_frame) / (upper_frame - lower_frame); - return (fraction < 0.5) ? lower_index : upper_index; + const float fraction = float(sample_frame - lower_frame) / (upper_frame - lower_frame); + return (fraction < 0.5) ? lower_index : upper_index; } const int BCAnimationCurve::get_interpolation_type(float sample_frame) const { - const int index = closest_index_below(sample_frame); - if (index < 0) - return BEZT_IPO_BEZ; - return fcurve->bezt[index].ipo; + const int index = closest_index_below(sample_frame); + if (index < 0) + return BEZT_IPO_BEZ; + return fcurve->bezt[index].ipo; } const FCurve *BCAnimationCurve::get_fcurve() const { - return fcurve; + return fcurve; } FCurve *BCAnimationCurve::get_edit_fcurve() { - if (!curve_is_local_copy) { - const int index = curve_key.get_array_index(); - const std::string &path = curve_key.get_path(); - fcurve = create_fcurve(index, path.c_str()); + if (!curve_is_local_copy) { + const int index = curve_key.get_array_index(); + const std::string &path = curve_key.get_path(); + fcurve = create_fcurve(index, path.c_str()); - /* Caution here: - Replacing the pointer here is OK only because the original value - of FCurve was a const pointer into Blender territory. We do not - touch that! We use the local copy to prepare data for export. - */ + /* Caution here: + Replacing the pointer here is OK only because the original value + of FCurve was a const pointer into Blender territory. We do not + touch that! We use the local copy to prepare data for export. + */ - curve_is_local_copy = true; - } - return fcurve; + curve_is_local_copy = true; + } + return fcurve; } void BCAnimationCurve::clean_handles() { - if (fcurve == NULL) - fcurve = get_edit_fcurve(); + if (fcurve == NULL) + fcurve = get_edit_fcurve(); - /* Keep old bezt data for copy)*/ - BezTriple *old_bezts = fcurve->bezt; - int totvert = fcurve->totvert; - fcurve->bezt = NULL; - fcurve->totvert = 0; + /* Keep old bezt data for copy)*/ + BezTriple *old_bezts = fcurve->bezt; + int totvert = fcurve->totvert; + fcurve->bezt = NULL; + fcurve->totvert = 0; - for (int i = 0; i < totvert; i++) { - BezTriple *bezt = &old_bezts[i]; - float x = bezt->vec[1][0]; - float y = bezt->vec[1][1]; - insert_vert_fcurve(fcurve, x, y, (eBezTriple_KeyframeType)BEZKEYTYPE(bezt), INSERTKEY_NOFLAGS); - BezTriple *lastb = fcurve->bezt + (fcurve->totvert - 1); - lastb->f1 = lastb->f2 = lastb->f3 = 0; - } + for (int i = 0; i < totvert; i++) { + BezTriple *bezt = &old_bezts[i]; + float x = bezt->vec[1][0]; + float y = bezt->vec[1][1]; + insert_vert_fcurve(fcurve, x, y, (eBezTriple_KeyframeType)BEZKEYTYPE(bezt), INSERTKEY_NOFLAGS); + BezTriple *lastb = fcurve->bezt + (fcurve->totvert - 1); + lastb->f1 = lastb->f2 = lastb->f3 = 0; + } - /* now free the memory used by the old BezTriples */ - if (old_bezts) - MEM_freeN(old_bezts); + /* now free the memory used by the old BezTriples */ + if (old_bezts) + MEM_freeN(old_bezts); } const bool BCAnimationCurve::is_transform_curve() const { - std::string channel_target = this->get_channel_target(); - return ( - is_rotation_curve() || - channel_target == "scale" || - channel_target == "location" - ); + std::string channel_target = this->get_channel_target(); + return (is_rotation_curve() || channel_target == "scale" || channel_target == "location"); } const bool BCAnimationCurve::is_rotation_curve() const { - std::string channel_target = this->get_channel_target(); - return ( - channel_target == "rotation" || - channel_target == "rotation_euler" || - channel_target == "rotation_quaternion" - ); + std::string channel_target = this->get_channel_target(); + return (channel_target == "rotation" || channel_target == "rotation_euler" || + channel_target == "rotation_quaternion"); } const float BCAnimationCurve::get_value(const float frame) { - if (fcurve) { - return evaluate_fcurve(fcurve, frame); - } - return 0; // TODO: handle case where neither sample nor fcu exist + if (fcurve) { + return evaluate_fcurve(fcurve, frame); + } + return 0; // TODO: handle case where neither sample nor fcu exist } void BCAnimationCurve::update_range(float val) { - if (val < min) { - min = val; - } - if (val > max) { - max = val; - } + if (val < min) { + min = val; + } + if (val > max) { + max = val; + } } void BCAnimationCurve::init_range(float val) { - min = max = val; + min = max = val; } void BCAnimationCurve::adjust_range(const int frame_index) { - if (fcurve && fcurve->totvert > 1) { - const float eval = evaluate_fcurve(fcurve, frame_index); + if (fcurve && fcurve->totvert > 1) { + const float eval = evaluate_fcurve(fcurve, frame_index); - int first_frame = fcurve->bezt[0].vec[1][0]; - if (first_frame == frame_index) { - init_range(eval); - } - else { - update_range(eval); - } - } + int first_frame = fcurve->bezt[0].vec[1][0]; + if (first_frame == frame_index) { + init_range(eval); + } + else { + update_range(eval); + } + } } void BCAnimationCurve::add_value(const float val, const int frame_index) { - FCurve *fcu = get_edit_fcurve(); - fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; - insert_vert_fcurve( - fcu, - frame_index, val, - BEZT_KEYTYPE_KEYFRAME, - INSERTKEY_NOFLAGS); + FCurve *fcu = get_edit_fcurve(); + fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; + insert_vert_fcurve(fcu, frame_index, val, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NOFLAGS); - if (fcu->totvert == 1) { - init_range(val); - } - else { - update_range(val); - } + if (fcu->totvert == 1) { + init_range(val); + } + else { + update_range(val); + } } bool BCAnimationCurve::add_value_from_matrix(const BCSample &sample, const int frame_index) { - int array_index = curve_key.get_array_index(); + int array_index = curve_key.get_array_index(); - /* transformation curves are feeded directly from the transformation matrix - * to resolve parent inverse matrix issues with object hierarchies. - * Maybe this can be unified with the - */ - const std::string channel_target = get_channel_target(); - float val = 0; - /* Pick the value from the sample according to the definition of the FCurve */ - bool good = sample.get_value(channel_target, array_index, &val); - if (good) { - add_value(val, frame_index); - } - return good; + /* transformation curves are feeded directly from the transformation matrix + * to resolve parent inverse matrix issues with object hierarchies. + * Maybe this can be unified with the + */ + const std::string channel_target = get_channel_target(); + float val = 0; + /* Pick the value from the sample according to the definition of the FCurve */ + bool good = sample.get_value(channel_target, array_index, &val); + if (good) { + add_value(val, frame_index); + } + return good; } bool BCAnimationCurve::add_value_from_rna(const int frame_index) { - PointerRNA ptr; - PropertyRNA *prop; - float value = 0.0f; - int array_index = curve_key.get_array_index(); - const std::string full_path = curve_key.get_full_path(); - - /* get property to read from, and get value as appropriate */ - bool path_resolved = RNA_path_resolve_full(&id_ptr, full_path.c_str(), &ptr, &prop, &array_index); - if (!path_resolved && array_index == 0) { - const std::string rna_path = curve_key.get_path(); - path_resolved = RNA_path_resolve_full(&id_ptr, rna_path.c_str(), &ptr, &prop, &array_index); - } - - if (path_resolved) { - bool is_array = RNA_property_array_check(prop); - if (is_array) { - /* array */ - if ((array_index >= 0) && (array_index < RNA_property_array_length(&ptr, prop))) { - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get_index(&ptr, prop, array_index); - break; - case PROP_INT: - value = (float)RNA_property_int_get_index(&ptr, prop, array_index); - break; - case PROP_FLOAT: - value = RNA_property_float_get_index(&ptr, prop, array_index); - break; - default: - break; - } - } - else { - fprintf(stderr, "Out of Bounds while reading data for Curve %s\n", curve_key.get_full_path().c_str()); - return false; - } - } - else { - /* not an array */ - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get(&ptr, prop); - break; - case PROP_INT: - value = (float)RNA_property_int_get(&ptr, prop); - break; - case PROP_FLOAT: - value = RNA_property_float_get(&ptr, prop); - break; - case PROP_ENUM: - value = (float)RNA_property_enum_get(&ptr, prop); - break; - default: - fprintf(stderr, "property type %d not supported for Curve %s\n", RNA_property_type(prop), curve_key.get_full_path().c_str()); - return false; - break; - } - } - } - else { - /* path couldn't be resolved */ - fprintf(stderr, "Path not recognized for Curve %s\n", curve_key.get_full_path().c_str()); - return false; - } - - add_value(value, frame_index); - return true; + PointerRNA ptr; + PropertyRNA *prop; + float value = 0.0f; + int array_index = curve_key.get_array_index(); + const std::string full_path = curve_key.get_full_path(); + + /* get property to read from, and get value as appropriate */ + bool path_resolved = RNA_path_resolve_full( + &id_ptr, full_path.c_str(), &ptr, &prop, &array_index); + if (!path_resolved && array_index == 0) { + const std::string rna_path = curve_key.get_path(); + path_resolved = RNA_path_resolve_full(&id_ptr, rna_path.c_str(), &ptr, &prop, &array_index); + } + + if (path_resolved) { + bool is_array = RNA_property_array_check(prop); + if (is_array) { + /* array */ + if ((array_index >= 0) && (array_index < RNA_property_array_length(&ptr, prop))) { + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + value = (float)RNA_property_boolean_get_index(&ptr, prop, array_index); + break; + case PROP_INT: + value = (float)RNA_property_int_get_index(&ptr, prop, array_index); + break; + case PROP_FLOAT: + value = RNA_property_float_get_index(&ptr, prop, array_index); + break; + default: + break; + } + } + else { + fprintf(stderr, + "Out of Bounds while reading data for Curve %s\n", + curve_key.get_full_path().c_str()); + return false; + } + } + else { + /* not an array */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + value = (float)RNA_property_boolean_get(&ptr, prop); + break; + case PROP_INT: + value = (float)RNA_property_int_get(&ptr, prop); + break; + case PROP_FLOAT: + value = RNA_property_float_get(&ptr, prop); + break; + case PROP_ENUM: + value = (float)RNA_property_enum_get(&ptr, prop); + break; + default: + fprintf(stderr, + "property type %d not supported for Curve %s\n", + RNA_property_type(prop), + curve_key.get_full_path().c_str()); + return false; + break; + } + } + } + else { + /* path couldn't be resolved */ + fprintf(stderr, "Path not recognized for Curve %s\n", curve_key.get_full_path().c_str()); + return false; + } + + add_value(value, frame_index); + return true; } void BCAnimationCurve::get_value_map(BCValueMap &value_map) { - value_map.clear(); - if (fcurve == NULL) { - return; - } + value_map.clear(); + if (fcurve == NULL) { + return; + } - for (int i = 0; i < fcurve->totvert; i++) { - const float frame = fcurve->bezt[i].vec[1][0]; - const float val = fcurve->bezt[i].vec[1][1]; - value_map[frame] = val; - } + for (int i = 0; i < fcurve->totvert; i++) { + const float frame = fcurve->bezt[i].vec[1][0]; + const float val = fcurve->bezt[i].vec[1][1]; + value_map[frame] = val; + } } void BCAnimationCurve::get_frames(BCFrames &frames) const { - frames.clear(); - if (fcurve) { - for (int i = 0; i < fcurve->totvert; i++) { - const float val = fcurve->bezt[i].vec[1][0]; - frames.push_back(val); - } - } + frames.clear(); + if (fcurve) { + for (int i = 0; i < fcurve->totvert; i++) { + const float val = fcurve->bezt[i].vec[1][0]; + frames.push_back(val); + } + } } void BCAnimationCurve::get_values(BCValues &values) const { - values.clear(); - if (fcurve) { - for (int i = 0; i < fcurve->totvert; i++) { - const float val = fcurve->bezt[i].vec[1][1]; - values.push_back(val); - } - } + values.clear(); + if (fcurve) { + for (int i = 0; i < fcurve->totvert; i++) { + const float val = fcurve->bezt[i].vec[1][1]; + values.push_back(val); + } + } } bool BCAnimationCurve::is_animated() { - static float MIN_DISTANCE = 0.00001; - return fabs(max - min) > MIN_DISTANCE; + static float MIN_DISTANCE = 0.00001; + return fabs(max - min) > MIN_DISTANCE; } +bool BCAnimationCurve::is_keyframe(int frame) +{ + if (this->fcurve == NULL) + return false; -bool BCAnimationCurve::is_keyframe(int frame) { - if (this->fcurve == NULL) - return false; - - for (int i = 0; i < fcurve->totvert; ++i) { - const int cframe = nearbyint(fcurve->bezt[i].vec[1][0]); - if (cframe == frame) - return true; - if (cframe > frame) - break; - } - return false; + for (int i = 0; i < fcurve->totvert; ++i) { + const int cframe = nearbyint(fcurve->bezt[i].vec[1][0]); + if (cframe == frame) + return true; + if (cframe > frame) + break; + } + return false; } /* Needed for adding a BCAnimationCurve into a BCAnimationCurveSet */ -inline bool operator< (const BCAnimationCurve& lhs, const BCAnimationCurve& rhs) { - std::string lhtgt = lhs.get_channel_target(); - std::string rhtgt = rhs.get_channel_target(); - if (lhtgt == rhtgt) - { - const int lha = lhs.get_channel_index(); - const int rha = rhs.get_channel_index(); - return lha < rha; - } - else - return lhtgt < rhtgt; +inline bool operator<(const BCAnimationCurve &lhs, const BCAnimationCurve &rhs) +{ + std::string lhtgt = lhs.get_channel_target(); + std::string rhtgt = rhs.get_channel_target(); + if (lhtgt == rhtgt) { + const int lha = lhs.get_channel_index(); + const int rha = rhs.get_channel_index(); + return lha < rha; + } + else + return lhtgt < rhtgt; } BCCurveKey::BCCurveKey() { - this->key_type = BC_ANIMATION_TYPE_OBJECT; - this->rna_path = ""; - this->curve_array_index = 0; - this->curve_subindex = -1; + this->key_type = BC_ANIMATION_TYPE_OBJECT; + this->rna_path = ""; + this->curve_array_index = 0; + this->curve_subindex = -1; } -BCCurveKey::BCCurveKey(const BC_animation_type type, const std::string path, const int array_index, const int subindex) +BCCurveKey::BCCurveKey(const BC_animation_type type, + const std::string path, + const int array_index, + const int subindex) { - this->key_type = type; - this->rna_path = path; - this->curve_array_index = array_index; - this->curve_subindex = subindex; + this->key_type = type; + this->rna_path = path; + this->curve_array_index = array_index; + this->curve_subindex = subindex; } void BCCurveKey::operator=(const BCCurveKey &other) { - this->key_type = other.key_type; - this->rna_path = other.rna_path; - this->curve_array_index = other.curve_array_index; - this->curve_subindex = other.curve_subindex; + this->key_type = other.key_type; + this->rna_path = other.rna_path; + this->curve_array_index = other.curve_array_index; + this->curve_subindex = other.curve_subindex; } const std::string BCCurveKey::get_full_path() const { - return this->rna_path + '[' + std::to_string(this->curve_array_index) + ']'; + return this->rna_path + '[' + std::to_string(this->curve_array_index) + ']'; } const std::string BCCurveKey::get_path() const { - return this->rna_path; + return this->rna_path; } const int BCCurveKey::get_array_index() const { - return this->curve_array_index; + return this->curve_array_index; } const int BCCurveKey::get_subindex() const { - return this->curve_subindex; + return this->curve_subindex; } void BCCurveKey::set_object_type(BC_animation_type object_type) { - this->key_type = object_type; + this->key_type = object_type; } const BC_animation_type BCCurveKey::get_animation_type() const { - return this->key_type; + return this->key_type; } const bool BCCurveKey::operator<(const BCCurveKey &other) const { - /* needed for using this class as key in maps and sets */ - if (this->key_type != other.key_type) - return this->key_type < other.key_type; + /* needed for using this class as key in maps and sets */ + if (this->key_type != other.key_type) + return this->key_type < other.key_type; - if (this->curve_subindex != other.curve_subindex) - return this->curve_subindex < other.curve_subindex; + if (this->curve_subindex != other.curve_subindex) + return this->curve_subindex < other.curve_subindex; - if (this->rna_path != other.rna_path) - return this->rna_path < other.rna_path; + if (this->rna_path != other.rna_path) + return this->rna_path < other.rna_path; - return this->curve_array_index < other.curve_array_index; + return this->curve_array_index < other.curve_array_index; } -BCBezTriple::BCBezTriple(BezTriple &bezt) : - bezt(bezt) {} +BCBezTriple::BCBezTriple(BezTriple &bezt) : bezt(bezt) +{ +} const float BCBezTriple::get_frame() const { - return bezt.vec[1][0]; + return bezt.vec[1][0]; } const float BCBezTriple::get_time(Scene *scene) const { - return FRA2TIME(bezt.vec[1][0]); + return FRA2TIME(bezt.vec[1][0]); } const float BCBezTriple::get_value() const { - return bezt.vec[1][1]; + return bezt.vec[1][1]; } const float BCBezTriple::get_angle() const { - return RAD2DEGF(get_value()); + return RAD2DEGF(get_value()); } void BCBezTriple::get_in_tangent(Scene *scene, float point[2], bool as_angle) const { - get_tangent(scene, point, as_angle, 0); + get_tangent(scene, point, as_angle, 0); } void BCBezTriple::get_out_tangent(Scene *scene, float point[2], bool as_angle) const { - get_tangent(scene, point, as_angle, 2); + get_tangent(scene, point, as_angle, 2); } void BCBezTriple::get_tangent(Scene *scene, float point[2], bool as_angle, int index) const { - point[0] = FRA2TIME(bezt.vec[index][0]); - if (bezt.ipo != BEZT_IPO_BEZ) { - /* We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data */ - point[0] = 0; - point[1] = 0; - } - else if (as_angle) { - point[1] = RAD2DEGF(bezt.vec[index][1]); - } - else { - point[1] = bezt.vec[index][1]; - } + point[0] = FRA2TIME(bezt.vec[index][0]); + if (bezt.ipo != BEZT_IPO_BEZ) { + /* We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data */ + point[0] = 0; + point[1] = 0; + } + else if (as_angle) { + point[1] = RAD2DEGF(bezt.vec[index][1]); + } + else { + point[1] = bezt.vec[index][1]; + } } diff --git a/source/blender/collada/BCAnimationCurve.h b/source/blender/collada/BCAnimationCurve.h index c01b3150dba..989ec1d0101 100644 --- a/source/blender/collada/BCAnimationCurve.h +++ b/source/blender/collada/BCAnimationCurve.h @@ -23,8 +23,7 @@ #include "collada_utils.h" #include "BCSampleData.h" -extern "C" -{ +extern "C" { #include "MEM_guardedalloc.h" #include "BKE_fcurve.h" #include "BKE_armature.h" @@ -43,106 +42,105 @@ typedef std::vector<float> BCTimes; typedef std::map<int, float> BCValueMap; typedef enum BC_animation_type { - BC_ANIMATION_TYPE_OBJECT, - BC_ANIMATION_TYPE_BONE, - BC_ANIMATION_TYPE_CAMERA, - BC_ANIMATION_TYPE_MATERIAL, - BC_ANIMATION_TYPE_LIGHT, + BC_ANIMATION_TYPE_OBJECT, + BC_ANIMATION_TYPE_BONE, + BC_ANIMATION_TYPE_CAMERA, + BC_ANIMATION_TYPE_MATERIAL, + BC_ANIMATION_TYPE_LIGHT, } BC_animation_type; class BCCurveKey { -private: - BC_animation_type key_type; - std::string rna_path; - int curve_array_index; - int curve_subindex; /* only needed for materials */ - -public: - - BCCurveKey(); - BCCurveKey(const BC_animation_type type, const std::string path, const int array_index, const int subindex = -1); - void operator=(const BCCurveKey &other); - const std::string get_full_path() const; - const std::string get_path() const; - const int get_array_index() const; - const int get_subindex() const; - void set_object_type(BC_animation_type object_type); - const BC_animation_type get_animation_type() const; - const bool operator<(const BCCurveKey &other) const; - + private: + BC_animation_type key_type; + std::string rna_path; + int curve_array_index; + int curve_subindex; /* only needed for materials */ + + public: + BCCurveKey(); + BCCurveKey(const BC_animation_type type, + const std::string path, + const int array_index, + const int subindex = -1); + void operator=(const BCCurveKey &other); + const std::string get_full_path() const; + const std::string get_path() const; + const int get_array_index() const; + const int get_subindex() const; + void set_object_type(BC_animation_type object_type); + const BC_animation_type get_animation_type() const; + const bool operator<(const BCCurveKey &other) const; }; class BCBezTriple { -public: - BezTriple & bezt; - - BCBezTriple(BezTriple &bezt); - const float get_frame() const; - const float get_time(Scene *scene) const; - const float get_value() const; - const float get_angle() const; - void get_in_tangent(Scene *scene, float point[2], bool as_angle) const; - void get_out_tangent(Scene *scene, float point[2], bool as_angle) const; - void get_tangent(Scene *scene, float point[2], bool as_angle, int index) const; - + public: + BezTriple &bezt; + + BCBezTriple(BezTriple &bezt); + const float get_frame() const; + const float get_time(Scene *scene) const; + const float get_value() const; + const float get_angle() const; + void get_in_tangent(Scene *scene, float point[2], bool as_angle) const; + void get_out_tangent(Scene *scene, float point[2], bool as_angle) const; + void get_tangent(Scene *scene, float point[2], bool as_angle, int index) const; }; class BCAnimationCurve { -private: - BCCurveKey curve_key; - float min = 0; - float max = 0; - - bool curve_is_local_copy = false; - FCurve *fcurve; - PointerRNA id_ptr; - void init_pointer_rna(Object *ob); - void delete_fcurve(FCurve *fcu); - FCurve *create_fcurve(int array_index, const char *rna_path); - void create_bezt(float frame, float output); - void update_range(float val); - void init_range(float val); - -public: - BCAnimationCurve(); - BCAnimationCurve(const BCAnimationCurve &other); - BCAnimationCurve(const BCCurveKey &key, Object *ob); - BCAnimationCurve(BCCurveKey key, Object *ob, FCurve *fcu); - ~BCAnimationCurve(); - - const bool is_of_animation_type(BC_animation_type type) const; - const int get_interpolation_type(float sample_frame) const; - bool is_animated(); - const bool is_transform_curve() const; - const bool is_rotation_curve() const; - bool is_keyframe(int frame); - void adjust_range(int frame); - - const std::string get_animation_name(Object *ob) const; /* xxx: this is collada specific */ - const std::string get_channel_target() const; - const int get_channel_index() const; - const int get_subindex() const; - const std::string get_rna_path() const; - const FCurve *get_fcurve() const; - const int sample_count() const; - - const float get_value(const float frame); - void get_values(BCValues &values) const; - void get_value_map(BCValueMap &value_map); - - void get_frames(BCFrames &frames) const; - - /* Curve edit functions create a copy of the underlaying FCurve */ - FCurve *get_edit_fcurve(); - bool add_value_from_rna(const int frame); - bool add_value_from_matrix(const BCSample &sample, const int frame); - void add_value(const float val, const int frame); - void clean_handles(); - - /* experimental stuff */ - const int closest_index_above(const float sample_frame, const int start_at) const; - const int closest_index_below(const float sample_frame) const; - + private: + BCCurveKey curve_key; + float min = 0; + float max = 0; + + bool curve_is_local_copy = false; + FCurve *fcurve; + PointerRNA id_ptr; + void init_pointer_rna(Object *ob); + void delete_fcurve(FCurve *fcu); + FCurve *create_fcurve(int array_index, const char *rna_path); + void create_bezt(float frame, float output); + void update_range(float val); + void init_range(float val); + + public: + BCAnimationCurve(); + BCAnimationCurve(const BCAnimationCurve &other); + BCAnimationCurve(const BCCurveKey &key, Object *ob); + BCAnimationCurve(BCCurveKey key, Object *ob, FCurve *fcu); + ~BCAnimationCurve(); + + const bool is_of_animation_type(BC_animation_type type) const; + const int get_interpolation_type(float sample_frame) const; + bool is_animated(); + const bool is_transform_curve() const; + const bool is_rotation_curve() const; + bool is_keyframe(int frame); + void adjust_range(int frame); + + const std::string get_animation_name(Object *ob) const; /* xxx: this is collada specific */ + const std::string get_channel_target() const; + const int get_channel_index() const; + const int get_subindex() const; + const std::string get_rna_path() const; + const FCurve *get_fcurve() const; + const int sample_count() const; + + const float get_value(const float frame); + void get_values(BCValues &values) const; + void get_value_map(BCValueMap &value_map); + + void get_frames(BCFrames &frames) const; + + /* Curve edit functions create a copy of the underlaying FCurve */ + FCurve *get_edit_fcurve(); + bool add_value_from_rna(const int frame); + bool add_value_from_matrix(const BCSample &sample, const int frame); + void add_value(const float val, const int frame); + void clean_handles(); + + /* experimental stuff */ + const int closest_index_above(const float sample_frame, const int start_at) const; + const int closest_index_below(const float sample_frame) const; }; typedef std::map<BCCurveKey, BCAnimationCurve *> BCAnimationCurveMap; diff --git a/source/blender/collada/BCAnimationSampler.cpp b/source/blender/collada/BCAnimationSampler.cpp index 7e504a0e745..9a281e2218b 100644 --- a/source/blender/collada/BCAnimationSampler.cpp +++ b/source/blender/collada/BCAnimationSampler.cpp @@ -19,7 +19,7 @@ #include <vector> #include <map> -#include <algorithm> // std::find +#include <algorithm> // std::find #include "ExportSettings.h" #include "BCAnimationCurve.h" @@ -44,269 +44,279 @@ extern "C" { static std::string EMPTY_STRING; static BCAnimationCurveMap BCEmptyAnimationCurves; -BCAnimationSampler::BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &object_set): - blender_context(blender_context) +BCAnimationSampler::BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &object_set) + : blender_context(blender_context) { - BCObjectSet::iterator it; - for (it = object_set.begin(); it != object_set.end(); ++it) { - Object *ob = *it; - add_object(ob); - } + BCObjectSet::iterator it; + for (it = object_set.begin(); it != object_set.end(); ++it) { + Object *ob = *it; + add_object(ob); + } } BCAnimationSampler::~BCAnimationSampler() { - BCAnimationObjectMap::iterator it; - for (it = objects.begin(); it != objects.end(); ++it) { - BCAnimation *animation = it->second; - delete animation; - } + BCAnimationObjectMap::iterator it; + for (it = objects.begin(); it != objects.end(); ++it) { + BCAnimation *animation = it->second; + delete animation; + } } void BCAnimationSampler::add_object(Object *ob) { - BCAnimation *animation = new BCAnimation(blender_context.get_context(), ob); - objects[ob] = animation; + BCAnimation *animation = new BCAnimation(blender_context.get_context(), ob); + objects[ob] = animation; - initialize_keyframes(animation->frame_set, ob); - initialize_curves(animation->curve_map, ob); + initialize_keyframes(animation->frame_set, ob); + initialize_curves(animation->curve_map, ob); } BCAnimationCurveMap *BCAnimationSampler::get_curves(Object *ob) { - BCAnimation &animation = *objects[ob]; - if (animation.curve_map.size() == 0) - initialize_curves(animation.curve_map, ob); - return &animation.curve_map; + BCAnimation &animation = *objects[ob]; + if (animation.curve_map.size() == 0) + initialize_curves(animation.curve_map, ob); + return &animation.curve_map; } -static void get_sample_frames(BCFrameSet &sample_frames, int sampling_rate, bool keyframe_at_end, Scene *scene) +static void get_sample_frames(BCFrameSet &sample_frames, + int sampling_rate, + bool keyframe_at_end, + Scene *scene) { - sample_frames.clear(); + sample_frames.clear(); - if (sampling_rate < 1) - return; // no sample frames in this case + if (sampling_rate < 1) + return; // no sample frames in this case - float sfra = scene->r.sfra; - float efra = scene->r.efra; + float sfra = scene->r.sfra; + float efra = scene->r.efra; - int frame_index; - for (frame_index = nearbyint(sfra); frame_index < efra; frame_index += sampling_rate) { - sample_frames.insert(frame_index); - } + int frame_index; + for (frame_index = nearbyint(sfra); frame_index < efra; frame_index += sampling_rate) { + sample_frames.insert(frame_index); + } - if (frame_index >= efra && keyframe_at_end) - { - sample_frames.insert(efra); - } + if (frame_index >= efra && keyframe_at_end) { + sample_frames.insert(efra); + } } static bool is_object_keyframe(Object *ob, int frame_index) { - return false; + return false; } static void add_keyframes_from(bAction *action, BCFrameSet &frameset) { - if (action) { - FCurve *fcu = NULL; - for (fcu = (FCurve *)action->curves.first; fcu; fcu = fcu->next) { - BezTriple *bezt = fcu->bezt; - for (int i = 0; i < fcu->totvert; bezt++, i++) { - int frame_index = nearbyint(bezt->vec[1][0]); - frameset.insert(frame_index); - } - } - } -} - -void BCAnimationSampler::check_property_is_animated(BCAnimation &animation, float *ref, float *val, std::string data_path, int length) -{ - for (int array_index =0; array_index < length; ++array_index) { - if (!bc_in_range(ref[length], val[length], 0.00001)) { - BCCurveKey key(BC_ANIMATION_TYPE_OBJECT, data_path, array_index); - BCAnimationCurveMap::iterator it = animation.curve_map.find(key); - if (it == animation.curve_map.end()) { - animation.curve_map[key] = new BCAnimationCurve(key, animation.get_reference()); - } - } - } -} - -void BCAnimationSampler::update_animation_curves(BCAnimation &animation, BCSample &sample, Object *ob, int frame) -{ - BCAnimationCurveMap::iterator it; - for (it = animation.curve_map.begin(); it != animation.curve_map.end(); ++it) { - BCAnimationCurve *curve = it->second; - if (curve->is_transform_curve()) { - curve->add_value_from_matrix(sample, frame); - } - else { - curve->add_value_from_rna(frame); - } - } + if (action) { + FCurve *fcu = NULL; + for (fcu = (FCurve *)action->curves.first; fcu; fcu = fcu->next) { + BezTriple *bezt = fcu->bezt; + for (int i = 0; i < fcu->totvert; bezt++, i++) { + int frame_index = nearbyint(bezt->vec[1][0]); + frameset.insert(frame_index); + } + } + } +} + +void BCAnimationSampler::check_property_is_animated( + BCAnimation &animation, float *ref, float *val, std::string data_path, int length) +{ + for (int array_index = 0; array_index < length; ++array_index) { + if (!bc_in_range(ref[length], val[length], 0.00001)) { + BCCurveKey key(BC_ANIMATION_TYPE_OBJECT, data_path, array_index); + BCAnimationCurveMap::iterator it = animation.curve_map.find(key); + if (it == animation.curve_map.end()) { + animation.curve_map[key] = new BCAnimationCurve(key, animation.get_reference()); + } + } + } +} + +void BCAnimationSampler::update_animation_curves(BCAnimation &animation, + BCSample &sample, + Object *ob, + int frame) +{ + BCAnimationCurveMap::iterator it; + for (it = animation.curve_map.begin(); it != animation.curve_map.end(); ++it) { + BCAnimationCurve *curve = it->second; + if (curve->is_transform_curve()) { + curve->add_value_from_matrix(sample, frame); + } + else { + curve->add_value_from_rna(frame); + } + } } BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool for_opensim) { - BCSample &ob_sample = sample_data.add(ob, frame_index); - - if (ob->type == OB_ARMATURE) { - bPoseChannel *pchan; - for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { - Bone *bone = pchan->bone; - Matrix bmat; - if (bc_bone_matrix_local_get(ob, bone, bmat, for_opensim)) { - ob_sample.add_bone_matrix(bone, bmat); - } - } - } - return ob_sample; -} - -void BCAnimationSampler::sample_scene( - int sampling_rate, - int keyframe_at_end, - bool for_opensim, - bool keep_keyframes, - BC_export_animation_type export_animation_type) -{ - Scene *scene = blender_context.get_scene(); - BCFrameSet scene_sample_frames; - get_sample_frames(scene_sample_frames, sampling_rate, keyframe_at_end, scene); - BCFrameSet::iterator it; - - int startframe = scene->r.sfra; - int endframe = scene->r.efra; - - for (int frame_index = startframe; frame_index <= endframe; ++frame_index) { - /* Loop over all frames and decide for each frame if sampling is necessary */ - bool is_scene_sample_frame = false; - bool needs_update = true; - if (scene_sample_frames.find(frame_index) != scene_sample_frames.end()) { - bc_update_scene(blender_context, frame_index); - needs_update = false; - is_scene_sample_frame = true; - } - - bool needs_sampling = is_scene_sample_frame || keep_keyframes || export_animation_type == BC_ANIMATION_EXPORT_KEYS; - if (!needs_sampling) { - continue; - } - - BCAnimationObjectMap::iterator obit; - for (obit = objects.begin(); obit != objects.end(); ++obit) { - Object *ob = obit->first; - BCAnimation *animation = obit->second; - BCFrameSet &object_keyframes = animation->frame_set; - if (is_scene_sample_frame || object_keyframes.find(frame_index) != object_keyframes.end()) { - - if (needs_update) { - bc_update_scene(blender_context, frame_index); - needs_update = false; - } - - BCSample &sample = sample_object(ob, frame_index, for_opensim); - update_animation_curves(*animation, sample, ob, frame_index); - } - } - } -} - -bool BCAnimationSampler::is_animated_by_constraint(Object *ob, ListBase *conlist, std::set<Object *> &animated_objects) -{ - bConstraint *con; - for (con = (bConstraint *)conlist->first; con; con = con->next) { - ListBase targets = { NULL, NULL }; - - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - - if (!bc_validateConstraints(con)) - continue; - - if (cti && cti->get_constraint_targets) { - bConstraintTarget *ct; - Object *obtar; - cti->get_constraint_targets(con, &targets); - for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { - obtar = ct->tar; - if (obtar) { - if (animated_objects.find(obtar) != animated_objects.end()) - return true; - } - } - } - } - return false; -} - -void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_objects, std::set<Object *> &candidates) -{ - bool found_more; - do { - found_more = false; - std::set<Object *>::iterator it; - for (it = candidates.begin(); it != candidates.end(); ++it) { - Object *cob = *it; - ListBase *conlist = get_active_constraints(cob); - if (is_animated_by_constraint(cob, conlist, animated_objects)) { - animated_objects.insert(cob); - candidates.erase(cob); - found_more = true; - break; - } - } - } while (found_more && candidates.size() > 0); -} - -void BCAnimationSampler::get_animated_from_export_set(std::set<Object *> &animated_objects, LinkNode &export_set) -{ - /* - Check if this object is animated. That is: Check if it has its own action, or - - - Check if it has constraints to other objects - - at least one of the other objects is animated as well - */ - - animated_objects.clear(); - std::set<Object *> static_objects; - std::set<Object *> candidates; - - LinkNode *node; - for (node = &export_set; node; node = node->next) { - Object *cob = (Object *)node->link; - if (bc_has_animations(cob)) { - animated_objects.insert(cob); - } - else { - ListBase conlist = cob->constraints; - if (conlist.first) - candidates.insert(cob); - } - } - find_depending_animated(animated_objects, candidates); + BCSample &ob_sample = sample_data.add(ob, frame_index); + + if (ob->type == OB_ARMATURE) { + bPoseChannel *pchan; + for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + Bone *bone = pchan->bone; + Matrix bmat; + if (bc_bone_matrix_local_get(ob, bone, bmat, for_opensim)) { + ob_sample.add_bone_matrix(bone, bmat); + } + } + } + return ob_sample; +} + +void BCAnimationSampler::sample_scene(int sampling_rate, + int keyframe_at_end, + bool for_opensim, + bool keep_keyframes, + BC_export_animation_type export_animation_type) +{ + Scene *scene = blender_context.get_scene(); + BCFrameSet scene_sample_frames; + get_sample_frames(scene_sample_frames, sampling_rate, keyframe_at_end, scene); + BCFrameSet::iterator it; + + int startframe = scene->r.sfra; + int endframe = scene->r.efra; + + for (int frame_index = startframe; frame_index <= endframe; ++frame_index) { + /* Loop over all frames and decide for each frame if sampling is necessary */ + bool is_scene_sample_frame = false; + bool needs_update = true; + if (scene_sample_frames.find(frame_index) != scene_sample_frames.end()) { + bc_update_scene(blender_context, frame_index); + needs_update = false; + is_scene_sample_frame = true; + } + + bool needs_sampling = is_scene_sample_frame || keep_keyframes || + export_animation_type == BC_ANIMATION_EXPORT_KEYS; + if (!needs_sampling) { + continue; + } + + BCAnimationObjectMap::iterator obit; + for (obit = objects.begin(); obit != objects.end(); ++obit) { + Object *ob = obit->first; + BCAnimation *animation = obit->second; + BCFrameSet &object_keyframes = animation->frame_set; + if (is_scene_sample_frame || object_keyframes.find(frame_index) != object_keyframes.end()) { + + if (needs_update) { + bc_update_scene(blender_context, frame_index); + needs_update = false; + } + + BCSample &sample = sample_object(ob, frame_index, for_opensim); + update_animation_curves(*animation, sample, ob, frame_index); + } + } + } +} + +bool BCAnimationSampler::is_animated_by_constraint(Object *ob, + ListBase *conlist, + std::set<Object *> &animated_objects) +{ + bConstraint *con; + for (con = (bConstraint *)conlist->first; con; con = con->next) { + ListBase targets = {NULL, NULL}; + + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + + if (!bc_validateConstraints(con)) + continue; + + if (cti && cti->get_constraint_targets) { + bConstraintTarget *ct; + Object *obtar; + cti->get_constraint_targets(con, &targets); + for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { + obtar = ct->tar; + if (obtar) { + if (animated_objects.find(obtar) != animated_objects.end()) + return true; + } + } + } + } + return false; +} + +void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_objects, + std::set<Object *> &candidates) +{ + bool found_more; + do { + found_more = false; + std::set<Object *>::iterator it; + for (it = candidates.begin(); it != candidates.end(); ++it) { + Object *cob = *it; + ListBase *conlist = get_active_constraints(cob); + if (is_animated_by_constraint(cob, conlist, animated_objects)) { + animated_objects.insert(cob); + candidates.erase(cob); + found_more = true; + break; + } + } + } while (found_more && candidates.size() > 0); +} + +void BCAnimationSampler::get_animated_from_export_set(std::set<Object *> &animated_objects, + LinkNode &export_set) +{ + /* + Check if this object is animated. That is: Check if it has its own action, or + + - Check if it has constraints to other objects + - at least one of the other objects is animated as well + */ + + animated_objects.clear(); + std::set<Object *> static_objects; + std::set<Object *> candidates; + + LinkNode *node; + for (node = &export_set; node; node = node->next) { + Object *cob = (Object *)node->link; + if (bc_has_animations(cob)) { + animated_objects.insert(cob); + } + else { + ListBase conlist = cob->constraints; + if (conlist.first) + candidates.insert(cob); + } + } + find_depending_animated(animated_objects, candidates); } void BCAnimationSampler::get_object_frames(BCFrames &frames, Object *ob) { - sample_data.get_frames(ob, frames); + sample_data.get_frames(ob, frames); } void BCAnimationSampler::get_bone_frames(BCFrames &frames, Object *ob, Bone *bone) { - sample_data.get_frames(ob, bone, frames); + sample_data.get_frames(ob, bone, frames); } bool BCAnimationSampler::get_bone_samples(BCMatrixSampleMap &samples, Object *ob, Bone *bone) { - sample_data.get_matrices(ob, bone, samples); - return bc_is_animated(samples); + sample_data.get_matrices(ob, bone, samples); + return bc_is_animated(samples); } bool BCAnimationSampler::get_object_samples(BCMatrixSampleMap &samples, Object *ob) { - sample_data.get_matrices(ob, samples); - return bc_is_animated(samples); + sample_data.get_matrices(ob, samples); + return bc_is_animated(samples); } #if 0 @@ -323,75 +333,73 @@ bool BCAnimationSampler::get_object_samples(BCMatrixSampleMap &samples, Object * */ void BCAnimationSampler::add_value_set( - BCAnimationCurve &curve, - BCFrameSampleMap &samples, - BC_export_animation_type animation_type) -{ - int array_index = curve.get_array_index(); - const BC_animation_transform_type tm_type = curve.get_transform_type(); - - BCFrameSampleMap::iterator it; - for (it = samples.begin(); it != samples.end(); ++it) { - const int frame_index = nearbyint(it->first); - if (animation_type == BC_ANIMATION_EXPORT_SAMPLES || curve.is_keyframe(frame_index)) { - - const BCSample *sample = it->second; - float val = 0; - - int subindex = curve.get_subindex(); - bool good; - if (subindex == -1) { - good = sample->get_value(tm_type, array_index, &val); - } - else { - good = sample->get_value(tm_type, array_index, &val, subindex); - } - - if (good) { - curve.add_value(val, frame_index); - } - } - } - curve.remove_unused_keyframes(); - curve.calchandles(); + BCAnimationCurve &curve, + BCFrameSampleMap &samples, + BC_export_animation_type animation_type) +{ + int array_index = curve.get_array_index(); + const BC_animation_transform_type tm_type = curve.get_transform_type(); + + BCFrameSampleMap::iterator it; + for (it = samples.begin(); it != samples.end(); ++it) { + const int frame_index = nearbyint(it->first); + if (animation_type == BC_ANIMATION_EXPORT_SAMPLES || curve.is_keyframe(frame_index)) { + + const BCSample *sample = it->second; + float val = 0; + + int subindex = curve.get_subindex(); + bool good; + if (subindex == -1) { + good = sample->get_value(tm_type, array_index, &val); + } + else { + good = sample->get_value(tm_type, array_index, &val, subindex); + } + + if (good) { + curve.add_value(val, frame_index); + } + } + } + curve.remove_unused_keyframes(); + curve.calchandles(); } #endif -void BCAnimationSampler::generate_transform( - Object *ob, - const BCCurveKey &key, - BCAnimationCurveMap &curves) +void BCAnimationSampler::generate_transform(Object *ob, + const BCCurveKey &key, + BCAnimationCurveMap &curves) { - BCAnimationCurveMap::const_iterator it = curves.find(key); - if (it == curves.end()) { - curves[key] = new BCAnimationCurve(key, ob); - } + BCAnimationCurveMap::const_iterator it = curves.find(key); + if (it == curves.end()) { + curves[key] = new BCAnimationCurve(key, ob); + } } -void BCAnimationSampler::generate_transforms( - Object *ob, - const std::string prep, - const BC_animation_type type, - BCAnimationCurveMap &curves) +void BCAnimationSampler::generate_transforms(Object *ob, + const std::string prep, + const BC_animation_type type, + BCAnimationCurveMap &curves) { - generate_transform(ob, BCCurveKey(type, prep+"location", 0), curves); - generate_transform(ob, BCCurveKey(type, prep+"location", 1), curves); - generate_transform(ob, BCCurveKey(type, prep+"location", 2), curves); - generate_transform(ob, BCCurveKey(type, prep+"rotation_euler", 0), curves); - generate_transform(ob, BCCurveKey(type, prep+"rotation_euler", 1), curves); - generate_transform(ob, BCCurveKey(type, prep+"rotation_euler", 2), curves); - generate_transform(ob, BCCurveKey(type, prep+"scale", 0), curves); - generate_transform(ob, BCCurveKey(type, prep+"scale", 1), curves); - generate_transform(ob, BCCurveKey(type, prep+"scale", 2), curves); + generate_transform(ob, BCCurveKey(type, prep + "location", 0), curves); + generate_transform(ob, BCCurveKey(type, prep + "location", 1), curves); + generate_transform(ob, BCCurveKey(type, prep + "location", 2), curves); + generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 0), curves); + generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 1), curves); + generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 2), curves); + generate_transform(ob, BCCurveKey(type, prep + "scale", 0), curves); + generate_transform(ob, BCCurveKey(type, prep + "scale", 1), curves); + generate_transform(ob, BCCurveKey(type, prep + "scale", 2), curves); } void BCAnimationSampler::generate_transforms(Object *ob, Bone *bone, BCAnimationCurveMap &curves) { - std::string prep = "pose.bones[\"" + std::string(bone->name) + "\"]."; - generate_transforms(ob, prep, BC_ANIMATION_TYPE_BONE, curves); + std::string prep = "pose.bones[\"" + std::string(bone->name) + "\"]."; + generate_transforms(ob, prep, BC_ANIMATION_TYPE_BONE, curves); - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) - generate_transforms(ob, child, curves); + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) + generate_transforms(ob, child, curves); } /** @@ -401,239 +409,240 @@ void BCAnimationSampler::generate_transforms(Object *ob, Bone *bone, BCAnimation */ void BCAnimationSampler::initialize_keyframes(BCFrameSet &frameset, Object *ob) { - frameset.clear(); - add_keyframes_from(bc_getSceneObjectAction(ob), frameset); - add_keyframes_from(bc_getSceneCameraAction(ob), frameset); - add_keyframes_from(bc_getSceneLightAction(ob), frameset); + frameset.clear(); + add_keyframes_from(bc_getSceneObjectAction(ob), frameset); + add_keyframes_from(bc_getSceneCameraAction(ob), frameset); + add_keyframes_from(bc_getSceneLightAction(ob), frameset); - for (int a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); - add_keyframes_from(bc_getSceneMaterialAction(ma), frameset); - } + for (int a = 0; a < ob->totcol; a++) { + Material *ma = give_current_material(ob, a + 1); + add_keyframes_from(bc_getSceneMaterialAction(ma), frameset); + } } void BCAnimationSampler::initialize_curves(BCAnimationCurveMap &curves, Object *ob) { - BC_animation_type object_type = BC_ANIMATION_TYPE_OBJECT; - - bAction *action = bc_getSceneObjectAction(ob); - if (action) { - FCurve *fcu = (FCurve *)action->curves.first; - - for (; fcu; fcu = fcu->next) { - object_type = BC_ANIMATION_TYPE_OBJECT; - if (ob->type == OB_ARMATURE) { - char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - if (boneName) { - object_type = BC_ANIMATION_TYPE_BONE; - } - } - - /* Adding action curves on object */ - BCCurveKey key(object_type, fcu->rna_path, fcu->array_index); - curves[key] = new BCAnimationCurve(key, ob, fcu); - } - } - - /* Add missing curves */ - object_type = BC_ANIMATION_TYPE_OBJECT; - generate_transforms(ob, EMPTY_STRING, object_type, curves); - if (ob->type == OB_ARMATURE) { - bArmature *arm = (bArmature *)ob->data; - for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next) - generate_transforms(ob, root_bone, curves); - } - - /* Add curves on Object->data actions */ - action = NULL; - if (ob->type == OB_CAMERA) { - action = bc_getSceneCameraAction(ob); - object_type = BC_ANIMATION_TYPE_CAMERA; - } - else if (ob->type == OB_LAMP) { - action = bc_getSceneLightAction(ob); - object_type = BC_ANIMATION_TYPE_LIGHT; - } - - if (action) { - /* Add light action or Camera action */ - FCurve *fcu = (FCurve *)action->curves.first; - for (; fcu; fcu = fcu->next) { - BCCurveKey key(object_type, fcu->rna_path, fcu->array_index); - curves[key] = new BCAnimationCurve(key, ob, fcu); - } - } - - /* Add curves on Object->material actions*/ - object_type = BC_ANIMATION_TYPE_MATERIAL; - for (int a = 0; a < ob->totcol; a++) { - /* Export Material parameter animations. */ - Material *ma = give_current_material(ob, a + 1); - if (ma) { - action = bc_getSceneMaterialAction(ma); - if (action) { - /* isMatAnim = true; */ - FCurve *fcu = (FCurve *)action->curves.first; - for (; fcu; fcu = fcu->next) { - BCCurveKey key(object_type, fcu->rna_path, fcu->array_index, a); - curves[key] = new BCAnimationCurve(key, ob, fcu); - } - } - } - } + BC_animation_type object_type = BC_ANIMATION_TYPE_OBJECT; + + bAction *action = bc_getSceneObjectAction(ob); + if (action) { + FCurve *fcu = (FCurve *)action->curves.first; + + for (; fcu; fcu = fcu->next) { + object_type = BC_ANIMATION_TYPE_OBJECT; + if (ob->type == OB_ARMATURE) { + char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); + if (boneName) { + object_type = BC_ANIMATION_TYPE_BONE; + } + } + + /* Adding action curves on object */ + BCCurveKey key(object_type, fcu->rna_path, fcu->array_index); + curves[key] = new BCAnimationCurve(key, ob, fcu); + } + } + + /* Add missing curves */ + object_type = BC_ANIMATION_TYPE_OBJECT; + generate_transforms(ob, EMPTY_STRING, object_type, curves); + if (ob->type == OB_ARMATURE) { + bArmature *arm = (bArmature *)ob->data; + for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next) + generate_transforms(ob, root_bone, curves); + } + + /* Add curves on Object->data actions */ + action = NULL; + if (ob->type == OB_CAMERA) { + action = bc_getSceneCameraAction(ob); + object_type = BC_ANIMATION_TYPE_CAMERA; + } + else if (ob->type == OB_LAMP) { + action = bc_getSceneLightAction(ob); + object_type = BC_ANIMATION_TYPE_LIGHT; + } + + if (action) { + /* Add light action or Camera action */ + FCurve *fcu = (FCurve *)action->curves.first; + for (; fcu; fcu = fcu->next) { + BCCurveKey key(object_type, fcu->rna_path, fcu->array_index); + curves[key] = new BCAnimationCurve(key, ob, fcu); + } + } + + /* Add curves on Object->material actions*/ + object_type = BC_ANIMATION_TYPE_MATERIAL; + for (int a = 0; a < ob->totcol; a++) { + /* Export Material parameter animations. */ + Material *ma = give_current_material(ob, a + 1); + if (ma) { + action = bc_getSceneMaterialAction(ma); + if (action) { + /* isMatAnim = true; */ + FCurve *fcu = (FCurve *)action->curves.first; + for (; fcu; fcu = fcu->next) { + BCCurveKey key(object_type, fcu->rna_path, fcu->array_index, a); + curves[key] = new BCAnimationCurve(key, ob, fcu); + } + } + } + } } /* ==================================================================== */ BCSample &BCSampleFrame::add(Object *ob) { - BCSample *sample = new BCSample(ob); - sampleMap[ob] = sample; - return *sample; + BCSample *sample = new BCSample(ob); + sampleMap[ob] = sample; + return *sample; } /* Get the matrix for the given key, returns Unity when the key does not exist */ const BCSample *BCSampleFrame::get_sample(Object *ob) const { - BCSampleMap::const_iterator it = sampleMap.find(ob); - if (it == sampleMap.end()) { - return NULL; - } - return it->second; + BCSampleMap::const_iterator it = sampleMap.find(ob); + if (it == sampleMap.end()) { + return NULL; + } + return it->second; } const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob) const { - BCSampleMap::const_iterator it = sampleMap.find(ob); - if (it == sampleMap.end()) { - return NULL; - } - BCSample *sample = it->second; - return &sample->get_matrix(); + BCSampleMap::const_iterator it = sampleMap.find(ob); + if (it == sampleMap.end()) { + return NULL; + } + BCSample *sample = it->second; + return &sample->get_matrix(); } /* Get the matrix for the given Bone, returns Unity when the Objewct is not sampled */ const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob, Bone *bone) const { - BCSampleMap::const_iterator it = sampleMap.find(ob); - if (it == sampleMap.end()) { - return NULL; - } + BCSampleMap::const_iterator it = sampleMap.find(ob); + if (it == sampleMap.end()) { + return NULL; + } - BCSample *sample = it->second; - const BCMatrix *bc_bone = sample->get_matrix(bone); - return bc_bone; + BCSample *sample = it->second; + const BCMatrix *bc_bone = sample->get_matrix(bone); + return bc_bone; } /* Check if the key is in this BCSampleFrame */ const bool BCSampleFrame::has_sample_for(Object *ob) const { - return sampleMap.find(ob) != sampleMap.end(); + return sampleMap.find(ob) != sampleMap.end(); } /* Check if the Bone is in this BCSampleFrame */ const bool BCSampleFrame::has_sample_for(Object *ob, Bone *bone) const { - const BCMatrix *bc_bone = get_sample_matrix(ob, bone); - return (bc_bone); + const BCMatrix *bc_bone = get_sample_matrix(ob, bone); + return (bc_bone); } /* ==================================================================== */ BCSample &BCSampleFrameContainer::add(Object *ob, int frame_index) { - BCSampleFrame &frame = sample_frames[frame_index]; - return frame.add(ob); + BCSampleFrame &frame = sample_frames[frame_index]; + return frame.add(ob); } - /* ====================================================== */ /* Below are the getters which we need to export the data */ /* ====================================================== */ /* Return either the BCSampleFrame or NULL if frame does not exist*/ -BCSampleFrame * BCSampleFrameContainer::get_frame(int frame_index) +BCSampleFrame *BCSampleFrameContainer::get_frame(int frame_index) { - BCSampleFrameMap::iterator it = sample_frames.find(frame_index); - BCSampleFrame *frame = (it == sample_frames.end()) ? NULL : &it->second; - return frame; + BCSampleFrameMap::iterator it = sample_frames.find(frame_index); + BCSampleFrame *frame = (it == sample_frames.end()) ? NULL : &it->second; + return frame; } /* Return a list of all frames that need to be sampled */ const int BCSampleFrameContainer::get_frames(std::vector<int> &frames) const { - frames.clear(); // safety; - BCSampleFrameMap::const_iterator it; - for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { - frames.push_back(it->first); - } - return frames.size(); + frames.clear(); // safety; + BCSampleFrameMap::const_iterator it; + for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { + frames.push_back(it->first); + } + return frames.size(); } const int BCSampleFrameContainer::get_frames(Object *ob, BCFrames &frames) const { - frames.clear(); // safety; - BCSampleFrameMap::const_iterator it; - for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { - const BCSampleFrame &frame = it->second; - if (frame.has_sample_for(ob)) { - frames.push_back(it->first); - } - } - return frames.size(); + frames.clear(); // safety; + BCSampleFrameMap::const_iterator it; + for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { + const BCSampleFrame &frame = it->second; + if (frame.has_sample_for(ob)) { + frames.push_back(it->first); + } + } + return frames.size(); } const int BCSampleFrameContainer::get_frames(Object *ob, Bone *bone, BCFrames &frames) const { - frames.clear(); // safety; - BCSampleFrameMap::const_iterator it; - for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { - const BCSampleFrame &frame = it->second; - if (frame.has_sample_for(ob, bone)) { - frames.push_back(it->first); - } - } - return frames.size(); + frames.clear(); // safety; + BCSampleFrameMap::const_iterator it; + for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { + const BCSampleFrame &frame = it->second; + if (frame.has_sample_for(ob, bone)) { + frames.push_back(it->first); + } + } + return frames.size(); } const int BCSampleFrameContainer::get_samples(Object *ob, BCFrameSampleMap &samples) const { - samples.clear(); // safety; - BCSampleFrameMap::const_iterator it; - for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { - const BCSampleFrame &frame = it->second; - const BCSample *sample = frame.get_sample(ob); - if (sample) { - samples[it->first] = sample; - } - } - return samples.size(); + samples.clear(); // safety; + BCSampleFrameMap::const_iterator it; + for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { + const BCSampleFrame &frame = it->second; + const BCSample *sample = frame.get_sample(ob); + if (sample) { + samples[it->first] = sample; + } + } + return samples.size(); } const int BCSampleFrameContainer::get_matrices(Object *ob, BCMatrixSampleMap &samples) const { - samples.clear(); // safety; - BCSampleFrameMap::const_iterator it; - for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { - const BCSampleFrame &frame = it->second; - const BCMatrix *matrix = frame.get_sample_matrix(ob); - if (matrix) { - samples[it->first] = matrix; - } - } - return samples.size(); -} - -const int BCSampleFrameContainer::get_matrices(Object *ob, Bone *bone, BCMatrixSampleMap &samples) const -{ - samples.clear(); // safety; - BCSampleFrameMap::const_iterator it; - for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { - const BCSampleFrame &frame = it->second; - const BCMatrix *sample = frame.get_sample_matrix(ob, bone); - if (sample) { - samples[it->first] = sample; - } - } - return samples.size(); + samples.clear(); // safety; + BCSampleFrameMap::const_iterator it; + for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { + const BCSampleFrame &frame = it->second; + const BCMatrix *matrix = frame.get_sample_matrix(ob); + if (matrix) { + samples[it->first] = matrix; + } + } + return samples.size(); +} + +const int BCSampleFrameContainer::get_matrices(Object *ob, + Bone *bone, + BCMatrixSampleMap &samples) const +{ + samples.clear(); // safety; + BCSampleFrameMap::const_iterator it; + for (it = sample_frames.begin(); it != sample_frames.end(); ++it) { + const BCSampleFrame &frame = it->second; + const BCMatrix *sample = frame.get_sample_matrix(ob, bone); + if (sample) { + samples[it->first] = sample; + } + } + return samples.size(); } diff --git a/source/blender/collada/BCAnimationSampler.h b/source/blender/collada/BCAnimationSampler.h index 95ec642ef33..6be386682e1 100644 --- a/source/blender/collada/BCAnimationSampler.h +++ b/source/blender/collada/BCAnimationSampler.h @@ -30,167 +30,171 @@ extern "C" { /* Collection of animation curves */ class BCAnimation { -private: - Object *reference = NULL; - bContext *mContext; - - -public: - BCFrameSet frame_set; - BCAnimationCurveMap curve_map; - - BCAnimation(bContext *C, Object *ob): - mContext(C) - { - Main *bmain = CTX_data_main(mContext); - reference = BKE_object_copy(bmain, ob); - } - - ~BCAnimation() - { - BCAnimationCurveMap::iterator it; - for (it = curve_map.begin(); it != curve_map.end(); ++it) { - delete it->second; - } - - if (reference && reference->id.us == 0) - { - Main *bmain = CTX_data_main(mContext); - BKE_id_delete(bmain, &reference->id); - } - curve_map.clear(); - } - - Object *get_reference() - { - return reference; - } + private: + Object *reference = NULL; + bContext *mContext; + + public: + BCFrameSet frame_set; + BCAnimationCurveMap curve_map; + + BCAnimation(bContext *C, Object *ob) : mContext(C) + { + Main *bmain = CTX_data_main(mContext); + reference = BKE_object_copy(bmain, ob); + } + + ~BCAnimation() + { + BCAnimationCurveMap::iterator it; + for (it = curve_map.begin(); it != curve_map.end(); ++it) { + delete it->second; + } + + if (reference && reference->id.us == 0) { + Main *bmain = CTX_data_main(mContext); + BKE_id_delete(bmain, &reference->id); + } + curve_map.clear(); + } + + Object *get_reference() + { + return reference; + } }; typedef std::map<Object *, BCAnimation *> BCAnimationObjectMap; class BCSampleFrame { - /* - Each frame on the timeline that needs to be sampled will have - one BCSampleFrame where we collect sample information about all objects - that need to be sampled for that frame. - */ - -private: - BCSampleMap sampleMap; - -public: - - ~BCSampleFrame() - { - BCSampleMap::iterator it; - for (it = sampleMap.begin(); it != sampleMap.end(); ++it) { - BCSample *sample = it->second; - delete sample; - } - sampleMap.clear(); - } - - BCSample &add(Object *ob); - - /* Following methods return NULL if object is not in the sampleMap*/ - const BCSample *get_sample(Object *ob) const; - const BCMatrix *get_sample_matrix(Object *ob) const; - const BCMatrix *get_sample_matrix(Object *ob, Bone *bone) const; - - const bool has_sample_for(Object *ob) const; - const bool has_sample_for(Object *ob, Bone *bone) const; + /* + Each frame on the timeline that needs to be sampled will have + one BCSampleFrame where we collect sample information about all objects + that need to be sampled for that frame. + */ + + private: + BCSampleMap sampleMap; + + public: + ~BCSampleFrame() + { + BCSampleMap::iterator it; + for (it = sampleMap.begin(); it != sampleMap.end(); ++it) { + BCSample *sample = it->second; + delete sample; + } + sampleMap.clear(); + } + + BCSample &add(Object *ob); + + /* Following methods return NULL if object is not in the sampleMap*/ + const BCSample *get_sample(Object *ob) const; + const BCMatrix *get_sample_matrix(Object *ob) const; + const BCMatrix *get_sample_matrix(Object *ob, Bone *bone) const; + + const bool has_sample_for(Object *ob) const; + const bool has_sample_for(Object *ob, Bone *bone) const; }; typedef std::map<int, BCSampleFrame> BCSampleFrameMap; class BCSampleFrameContainer { - /* - * The BCSampleFrameContainer stores a map of BCSampleFrame objects - * with the timeline frame as key. - * - * Some details on the purpose: - * An Animation is made of multiple FCurves where each FCurve can - * have multiple keyframes. When we want to export the animation we - * also can decide whether we want to export the keyframes or a set - * of sample frames at equidistant locations (sample period). - * In any case we must resample first need to resample it fully - * to resolve things like: - * - * - animations by constraints - * - animations by drivers - * - * For this purpose we need to step through the entire animation and - * then sample each frame that contains at least one keyFrame or - * sampleFrame. Then for each frame we have to store the transform - * information for all exported objects in a BCSampleframe - * - * The entire set of BCSampleframes is finally collected into - * a BCSampleframneContainer - */ - -private: - BCSampleFrameMap sample_frames; - -public: - - ~BCSampleFrameContainer() - { - } - - BCSample &add(Object *ob, int frame_index); - BCSampleFrame *get_frame(int frame_index); // returns NULL if frame does not exist - - const int get_frames(std::vector<int> &frames) const; - const int get_frames(Object *ob, BCFrames &frames) const; - const int get_frames(Object *ob, Bone *bone, BCFrames &frames) const; - - const int get_samples(Object *ob, BCFrameSampleMap &samples) const; - const int get_matrices(Object *ob, BCMatrixSampleMap &matrices) const; - const int get_matrices(Object *ob, Bone *bone, BCMatrixSampleMap &bones) const; + /* + * The BCSampleFrameContainer stores a map of BCSampleFrame objects + * with the timeline frame as key. + * + * Some details on the purpose: + * An Animation is made of multiple FCurves where each FCurve can + * have multiple keyframes. When we want to export the animation we + * also can decide whether we want to export the keyframes or a set + * of sample frames at equidistant locations (sample period). + * In any case we must resample first need to resample it fully + * to resolve things like: + * + * - animations by constraints + * - animations by drivers + * + * For this purpose we need to step through the entire animation and + * then sample each frame that contains at least one keyFrame or + * sampleFrame. Then for each frame we have to store the transform + * information for all exported objects in a BCSampleframe + * + * The entire set of BCSampleframes is finally collected into + * a BCSampleframneContainer + */ + + private: + BCSampleFrameMap sample_frames; + + public: + ~BCSampleFrameContainer() + { + } + + BCSample &add(Object *ob, int frame_index); + BCSampleFrame *get_frame(int frame_index); // returns NULL if frame does not exist + + const int get_frames(std::vector<int> &frames) const; + const int get_frames(Object *ob, BCFrames &frames) const; + const int get_frames(Object *ob, Bone *bone, BCFrames &frames) const; + + const int get_samples(Object *ob, BCFrameSampleMap &samples) const; + const int get_matrices(Object *ob, BCMatrixSampleMap &matrices) const; + const int get_matrices(Object *ob, Bone *bone, BCMatrixSampleMap &bones) const; }; class BCAnimationSampler { -private: - BlenderContext &blender_context; - BCSampleFrameContainer sample_data; - BCAnimationObjectMap objects; - - void generate_transform(Object *ob, const BCCurveKey &key, BCAnimationCurveMap &curves); - void generate_transforms(Object *ob, const std::string prep, const BC_animation_type type, BCAnimationCurveMap &curves); - void generate_transforms(Object *ob, Bone *bone, BCAnimationCurveMap &curves); - - void initialize_curves(BCAnimationCurveMap &curves, Object *ob); - void initialize_keyframes(BCFrameSet &frameset, Object *ob); - BCSample &sample_object(Object *ob, int frame_index, bool for_opensim); - void update_animation_curves(BCAnimation &animation, BCSample &sample, Object *ob, int frame_index); - void check_property_is_animated(BCAnimation &animation, float *ref, float *val, std::string data_path, int length); - -public: - BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &animated_subset); - ~BCAnimationSampler(); - - void add_object(Object *ob); - - void sample_scene( - int sampling_rate, - int keyframe_at_end, - bool for_opensim, - bool keep_keyframes, - BC_export_animation_type export_animation_type); - - BCAnimationCurveMap *get_curves(Object *ob); - void get_object_frames(BCFrames &frames, Object *ob); - bool get_object_samples(BCMatrixSampleMap &samples, Object *ob); - void get_bone_frames(BCFrames &frames, Object *ob, Bone *bone); - bool get_bone_samples(BCMatrixSampleMap &samples, Object *ob, Bone *bone); - - static void get_animated_from_export_set(std::set<Object *> &animated_objects, LinkNode &export_set); - static void find_depending_animated(std::set<Object *> &animated_objects, std::set<Object *> &candidates); - static bool is_animated_by_constraint(Object *ob, ListBase *conlist, std::set<Object *> &animated_objects); - + private: + BlenderContext &blender_context; + BCSampleFrameContainer sample_data; + BCAnimationObjectMap objects; + + void generate_transform(Object *ob, const BCCurveKey &key, BCAnimationCurveMap &curves); + void generate_transforms(Object *ob, + const std::string prep, + const BC_animation_type type, + BCAnimationCurveMap &curves); + void generate_transforms(Object *ob, Bone *bone, BCAnimationCurveMap &curves); + + void initialize_curves(BCAnimationCurveMap &curves, Object *ob); + void initialize_keyframes(BCFrameSet &frameset, Object *ob); + BCSample &sample_object(Object *ob, int frame_index, bool for_opensim); + void update_animation_curves(BCAnimation &animation, + BCSample &sample, + Object *ob, + int frame_index); + void check_property_is_animated( + BCAnimation &animation, float *ref, float *val, std::string data_path, int length); + + public: + BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &animated_subset); + ~BCAnimationSampler(); + + void add_object(Object *ob); + + void sample_scene(int sampling_rate, + int keyframe_at_end, + bool for_opensim, + bool keep_keyframes, + BC_export_animation_type export_animation_type); + + BCAnimationCurveMap *get_curves(Object *ob); + void get_object_frames(BCFrames &frames, Object *ob); + bool get_object_samples(BCMatrixSampleMap &samples, Object *ob); + void get_bone_frames(BCFrames &frames, Object *ob, Bone *bone); + bool get_bone_samples(BCMatrixSampleMap &samples, Object *ob, Bone *bone); + + static void get_animated_from_export_set(std::set<Object *> &animated_objects, + LinkNode &export_set); + static void find_depending_animated(std::set<Object *> &animated_objects, + std::set<Object *> &candidates); + static bool is_animated_by_constraint(Object *ob, + ListBase *conlist, + std::set<Object *> &animated_objects); }; #endif diff --git a/source/blender/collada/BCSampleData.cpp b/source/blender/collada/BCSampleData.cpp index 812ac3c2a5a..6e17598469f 100644 --- a/source/blender/collada/BCSampleData.cpp +++ b/source/blender/collada/BCSampleData.cpp @@ -20,161 +20,158 @@ #include "BCSampleData.h" #include "collada_utils.h" -BCSample::BCSample(Object *ob): - obmat(ob) -{} +BCSample::BCSample(Object *ob) : obmat(ob) +{ +} BCSample::~BCSample() { - BCBoneMatrixMap::iterator it; - for (it = bonemats.begin(); it != bonemats.end(); ++it) { - delete it->second; - } + BCBoneMatrixMap::iterator it; + for (it = bonemats.begin(); it != bonemats.end(); ++it) { + delete it->second; + } } void BCSample::add_bone_matrix(Bone *bone, Matrix &mat) { - BCMatrix *matrix; - BCBoneMatrixMap::const_iterator it = bonemats.find(bone); - if (it != bonemats.end()) { - throw std::invalid_argument("bone " + std::string(bone->name) + " already defined before"); - } - matrix = new BCMatrix(mat); - bonemats[bone] = matrix; + BCMatrix *matrix; + BCBoneMatrixMap::const_iterator it = bonemats.find(bone); + if (it != bonemats.end()) { + throw std::invalid_argument("bone " + std::string(bone->name) + " already defined before"); + } + matrix = new BCMatrix(mat); + bonemats[bone] = matrix; } BCMatrix::BCMatrix(Matrix &mat) { - set_transform(mat); + set_transform(mat); } BCMatrix::BCMatrix(Object *ob) { - set_transform(ob); + set_transform(ob); } void BCMatrix::set_transform(Matrix &mat) { - copy_m4_m4(matrix, mat); - mat4_decompose(this->loc, this->q, this->size, mat); - quat_to_eul(this->rot, this->q); + copy_m4_m4(matrix, mat); + mat4_decompose(this->loc, this->q, this->size, mat); + quat_to_eul(this->rot, this->q); } void BCMatrix::set_transform(Object *ob) { - Matrix lmat; + Matrix lmat; - BKE_object_matrix_local_get(ob, lmat); - copy_m4_m4(matrix, lmat); + BKE_object_matrix_local_get(ob, lmat); + copy_m4_m4(matrix, lmat); - mat4_decompose(this->loc, this->q, this->size, lmat); - quat_to_compatible_eul(this->rot, ob->rot, this->q); + mat4_decompose(this->loc, this->q, this->size, lmat); + quat_to_compatible_eul(this->rot, ob->rot, this->q); } const BCMatrix *BCSample::get_matrix(Bone *bone) const { - BCBoneMatrixMap::const_iterator it = bonemats.find(bone); - if (it == bonemats.end()) { - return NULL; - } - return it->second; + BCBoneMatrixMap::const_iterator it = bonemats.find(bone); + if (it == bonemats.end()) { + return NULL; + } + return it->second; } const BCMatrix &BCSample::get_matrix() const { - return obmat; + return obmat; } - /* Get channel value */ const bool BCSample::get_value(std::string channel_target, const int array_index, float *val) const { - if (channel_target == "location") { - *val = obmat.location()[array_index]; - } - else if (channel_target == "scale") { - *val = obmat.scale()[array_index]; - } - else if (channel_target == "rotation" || - channel_target == "rotation_euler") - { - *val = obmat.rotation()[array_index]; - } - else if (channel_target == "rotation_quat") { - *val = obmat.quat()[array_index]; - } - else { - *val = 0; - return false; - } - - return true; + if (channel_target == "location") { + *val = obmat.location()[array_index]; + } + else if (channel_target == "scale") { + *val = obmat.scale()[array_index]; + } + else if (channel_target == "rotation" || channel_target == "rotation_euler") { + *val = obmat.rotation()[array_index]; + } + else if (channel_target == "rotation_quat") { + *val = obmat.quat()[array_index]; + } + else { + *val = 0; + return false; + } + + return true; } void BCMatrix::copy(Matrix &out, Matrix &in) { - /* destination comes first: */ - memcpy(out, in, sizeof(Matrix)); + /* destination comes first: */ + memcpy(out, in, sizeof(Matrix)); } void BCMatrix::transpose(Matrix &mat) { - transpose_m4(mat); + transpose_m4(mat); } void BCMatrix::sanitize(Matrix &mat, int precision) { - bc_sanitize_mat(mat, precision); + bc_sanitize_mat(mat, precision); } void BCMatrix::unit() { - unit_m4(matrix); + unit_m4(matrix); } /* We need double here because the OpenCollada API needs it. precision = -1 indicates to not limit the precision */ -void BCMatrix::get_matrix(double(&mat)[4][4], const bool transposed, const int precision) const +void BCMatrix::get_matrix(double (&mat)[4][4], const bool transposed, const int precision) const { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) { - float val = (transposed) ? matrix[j][i] : matrix[i][j]; - if (precision >= 0) - val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); - mat[i][j] = val; - } + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) { + float val = (transposed) ? matrix[j][i] : matrix[i][j]; + if (precision >= 0) + val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); + mat[i][j] = val; + } } const bool BCMatrix::in_range(const BCMatrix &other, float distance) const { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - if (fabs(other.matrix[i][j] - matrix[i][j]) > distance) { - return false; - } - } - } - return true; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (fabs(other.matrix[i][j] - matrix[i][j]) > distance) { + return false; + } + } + } + return true; } -float(&BCMatrix::location() const)[3] +float (&BCMatrix::location() const)[3] { - return loc; + return loc; } -float(&BCMatrix::rotation() const)[3] +float (&BCMatrix::rotation() const)[3] { - return rot; + return rot; } -float(&BCMatrix::scale() const)[3] +float (&BCMatrix::scale() const)[3] { - return size; + return size; } -float(&BCMatrix::quat() const)[4] +float (&BCMatrix::quat() const)[4] { - return q; + return q; } diff --git a/source/blender/collada/BCSampleData.h b/source/blender/collada/BCSampleData.h index ec7f14f8c3a..9cb56c95e0f 100644 --- a/source/blender/collada/BCSampleData.h +++ b/source/blender/collada/BCSampleData.h @@ -24,8 +24,7 @@ #include <map> #include <algorithm> -extern "C" -{ +extern "C" { #include "BKE_object.h" #include "BLI_math_rotation.h" #include "DNA_object_types.h" @@ -39,54 +38,52 @@ typedef float(Matrix)[4][4]; class BCMatrix { -private: - mutable float matrix[4][4]; - mutable float size[3]; - mutable float rot[3]; - mutable float loc[3]; - mutable float q[4]; - - void unit(); - void copy(Matrix &r, Matrix &a); - void set_transform(Object *ob); - void set_transform(Matrix &mat); - -public: - - float(&location() const)[3]; - float(&rotation() const)[3]; - float(&scale() const)[3]; - float(&quat() const)[4]; - - BCMatrix(Matrix &mat); - BCMatrix(Object *ob); - - void get_matrix(double(&mat)[4][4], const bool transposed = false, const int precision = -1) const; - - const bool in_range(const BCMatrix &other, float distance) const; - static void sanitize(Matrix &matrix, int precision); - static void transpose(Matrix &matrix); - + private: + mutable float matrix[4][4]; + mutable float size[3]; + mutable float rot[3]; + mutable float loc[3]; + mutable float q[4]; + + void unit(); + void copy(Matrix &r, Matrix &a); + void set_transform(Object *ob); + void set_transform(Matrix &mat); + + public: + float (&location() const)[3]; + float (&rotation() const)[3]; + float (&scale() const)[3]; + float (&quat() const)[4]; + + BCMatrix(Matrix &mat); + BCMatrix(Object *ob); + + void get_matrix(double (&mat)[4][4], + const bool transposed = false, + const int precision = -1) const; + + const bool in_range(const BCMatrix &other, float distance) const; + static void sanitize(Matrix &matrix, int precision); + static void transpose(Matrix &matrix); }; typedef std::map<Bone *, BCMatrix *> BCBoneMatrixMap; -class BCSample{ -private: - - BCMatrix obmat; - BCBoneMatrixMap bonemats; /* For Armature animation */ - -public: - BCSample(Object *ob); - ~BCSample(); +class BCSample { + private: + BCMatrix obmat; + BCBoneMatrixMap bonemats; /* For Armature animation */ - void add_bone_matrix(Bone *bone, Matrix &mat); + public: + BCSample(Object *ob); + ~BCSample(); - const bool get_value(std::string channel_target, const int array_index, float *val) const; - const BCMatrix &get_matrix() const; - const BCMatrix *get_matrix(Bone *bone) const; // returns NULL if bone is not animated + void add_bone_matrix(Bone *bone, Matrix &mat); + const bool get_value(std::string channel_target, const int array_index, float *val) const; + const BCMatrix &get_matrix() const; + const BCMatrix *get_matrix(Bone *bone) const; // returns NULL if bone is not animated }; typedef std::map<Object *, BCSample *> BCSampleMap; diff --git a/source/blender/collada/BlenderContext.cpp b/source/blender/collada/BlenderContext.cpp index 8713a8b6a19..384f235e00c 100644 --- a/source/blender/collada/BlenderContext.cpp +++ b/source/blender/collada/BlenderContext.cpp @@ -23,49 +23,49 @@ BlenderContext::BlenderContext(bContext *C) { - context = C; - main = CTX_data_main(C); - scene = CTX_data_scene(C); - view_layer = CTX_data_view_layer(C); - depsgraph = nullptr; // create only when needed + context = C; + main = CTX_data_main(C); + scene = CTX_data_scene(C); + view_layer = CTX_data_view_layer(C); + depsgraph = nullptr; // create only when needed } bContext *BlenderContext::get_context() { - return context; + return context; } Depsgraph *BlenderContext::get_depsgraph() { - if (!depsgraph) { - depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); - } - return depsgraph; + if (!depsgraph) { + depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); + } + return depsgraph; } Scene *BlenderContext::get_scene() { - return scene; + return scene; } Scene *BlenderContext::get_evaluated_scene() { - Scene *scene_eval = DEG_get_evaluated_scene(get_depsgraph()); - return scene_eval; + Scene *scene_eval = DEG_get_evaluated_scene(get_depsgraph()); + return scene_eval; } Object *BlenderContext::get_evaluated_object(Object *ob) { - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - return ob_eval; + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + return ob_eval; } ViewLayer *BlenderContext::get_view_layer() { - return view_layer; + return view_layer; } Main *BlenderContext::get_main() { - return main; + return main; } diff --git a/source/blender/collada/BlenderContext.h b/source/blender/collada/BlenderContext.h index c6c9063e253..f79f3a52507 100644 --- a/source/blender/collada/BlenderContext.h +++ b/source/blender/collada/BlenderContext.h @@ -29,24 +29,23 @@ extern "C" { #include "DEG_depsgraph_query.h" } -class BlenderContext -{ -private: - bContext *context; - Depsgraph *depsgraph; - Scene *scene; - ViewLayer *view_layer; - Main *main; +class BlenderContext { + private: + bContext *context; + Depsgraph *depsgraph; + Scene *scene; + ViewLayer *view_layer; + Main *main; -public: - BlenderContext(bContext *C); - bContext *get_context(); - Depsgraph *get_depsgraph(); - Scene *get_scene(); - Scene *get_evaluated_scene(); - Object *get_evaluated_object(Object *ob); - ViewLayer *get_view_layer(); - Main *get_main(); + public: + BlenderContext(bContext *C); + bContext *get_context(); + Depsgraph *get_depsgraph(); + Scene *get_scene(); + Scene *get_evaluated_scene(); + Object *get_evaluated_object(Object *ob); + ViewLayer *get_view_layer(); + Main *get_main(); }; #endif diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt index 7a02068f42d..d104d01af56 100644 --- a/source/blender/collada/CMakeLists.txt +++ b/source/blender/collada/CMakeLists.txt @@ -35,110 +35,110 @@ ELSE() ENDIF() set(INC - . - ../blenkernel - ../blenlib - ../blentranslation - ../depsgraph - ../editors/include - ../makesdna - ../makesrna - ../windowmanager - ../imbuf - ../../../intern/guardedalloc - ../ikplugin - ../../../intern/iksolver/extern - ../bmesh + . + ../blenkernel + ../blenlib + ../blentranslation + ../depsgraph + ../editors/include + ../makesdna + ../makesrna + ../windowmanager + ../imbuf + ../../../intern/guardedalloc + ../ikplugin + ../../../intern/iksolver/extern + ../bmesh ) set(INC_SYS - ${OPENCOLLADA_INCLUDE_DIRS} + ${OPENCOLLADA_INCLUDE_DIRS} ) set(SRC - AnimationClipExporter.cpp - AnimationExporter.cpp - AnimationImporter.cpp - ArmatureExporter.cpp - ArmatureImporter.cpp - BCAnimationCurve.cpp - BCAnimationSampler.cpp - BCSampleData.cpp - BlenderContext.cpp - CameraExporter.cpp - ControllerExporter.cpp - DocumentExporter.cpp - DocumentImporter.cpp - EffectExporter.cpp - ErrorHandler.cpp - ExportSettings.cpp - ExtraHandler.cpp - ExtraTags.cpp - GeometryExporter.cpp - ImageExporter.cpp - ImportSettings.cpp - InstanceWriter.cpp - LightExporter.cpp - MaterialExporter.cpp - Materials.cpp - MeshImporter.cpp - SceneExporter.cpp - SkinInfo.cpp - TransformReader.cpp - TransformWriter.cpp - collada.cpp - collada_internal.cpp - collada_utils.cpp + AnimationClipExporter.cpp + AnimationExporter.cpp + AnimationImporter.cpp + ArmatureExporter.cpp + ArmatureImporter.cpp + BCAnimationCurve.cpp + BCAnimationSampler.cpp + BCSampleData.cpp + BlenderContext.cpp + CameraExporter.cpp + ControllerExporter.cpp + DocumentExporter.cpp + DocumentImporter.cpp + EffectExporter.cpp + ErrorHandler.cpp + ExportSettings.cpp + ExtraHandler.cpp + ExtraTags.cpp + GeometryExporter.cpp + ImageExporter.cpp + ImportSettings.cpp + InstanceWriter.cpp + LightExporter.cpp + MaterialExporter.cpp + Materials.cpp + MeshImporter.cpp + SceneExporter.cpp + SkinInfo.cpp + TransformReader.cpp + TransformWriter.cpp + collada.cpp + collada_internal.cpp + collada_utils.cpp - AnimationClipExporter.h - AnimationExporter.h - AnimationImporter.h - ArmatureExporter.h - ArmatureImporter.h - BCAnimationCurve.h - BCAnimationSampler.h - BCSampleData.h - BlenderContext.h - CameraExporter.h - ControllerExporter.h - DocumentExporter.h - DocumentImporter.h - EffectExporter.h - ErrorHandler.h - ExportSettings.h - ExtraHandler.h - ExtraTags.h - GeometryExporter.h - ImageExporter.h - ImportSettings.h - InstanceWriter.h - LightExporter.h - MaterialExporter.h - Materials.h - MeshImporter.h - SceneExporter.h - SkinInfo.h - TransformReader.h - TransformWriter.h - collada.h - collada_internal.h - collada_utils.h + AnimationClipExporter.h + AnimationExporter.h + AnimationImporter.h + ArmatureExporter.h + ArmatureImporter.h + BCAnimationCurve.h + BCAnimationSampler.h + BCSampleData.h + BlenderContext.h + CameraExporter.h + ControllerExporter.h + DocumentExporter.h + DocumentImporter.h + EffectExporter.h + ErrorHandler.h + ExportSettings.h + ExtraHandler.h + ExtraTags.h + GeometryExporter.h + ImageExporter.h + ImportSettings.h + InstanceWriter.h + LightExporter.h + MaterialExporter.h + Materials.h + MeshImporter.h + SceneExporter.h + SkinInfo.h + TransformReader.h + TransformWriter.h + collada.h + collada_internal.h + collada_utils.h ) set(LIB ) if(WITH_BUILDINFO) - add_definitions(-DWITH_BUILDINFO) + add_definitions(-DWITH_BUILDINFO) endif() if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) endif() if(CMAKE_COMPILER_IS_GNUCXX) - # COLLADAFWArray.h gives error with gcc 4.5 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") + # COLLADAFWArray.h gives error with gcc 4.5 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") endif() blender_add_lib(bf_collada "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp index 618754e1dab..d318a90909e 100644 --- a/source/blender/collada/CameraExporter.cpp +++ b/source/blender/collada/CameraExporter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - #include <string> #include "COLLADASWCamera.h" @@ -30,71 +29,71 @@ extern "C" { #include "collada_internal.h" -CamerasExporter::CamerasExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryCameras(sw), export_settings(export_settings) { +CamerasExporter::CamerasExporter(COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings) + : COLLADASW::LibraryCameras(sw), export_settings(export_settings) +{ } template<class Functor> void forEachCameraObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { - LinkNode *node; - for (node = export_set; node; node = node->next) { - Object *ob = (Object *)node->link; + LinkNode *node; + for (node = export_set; node; node = node->next) { + Object *ob = (Object *)node->link; - if (ob->type == OB_CAMERA && ob->data) { - f(ob, sce); - } - } + if (ob->type == OB_CAMERA && ob->data) { + f(ob, sce); + } + } } void CamerasExporter::exportCameras(Scene *sce) { - openLibrary(); + openLibrary(); - forEachCameraObjectInExportSet(sce, *this, this->export_settings->export_set); + forEachCameraObjectInExportSet(sce, *this, this->export_settings->export_set); - closeLibrary(); + closeLibrary(); } void CamerasExporter::operator()(Object *ob, Scene *sce) { - Camera *cam = (Camera *)ob->data; - std::string cam_id(get_camera_id(ob)); - std::string cam_name(id_name(cam)); + Camera *cam = (Camera *)ob->data; + std::string cam_id(get_camera_id(ob)); + std::string cam_name(id_name(cam)); - switch (cam->type) { - case CAM_PANO: - case CAM_PERSP: - { - COLLADASW::PerspectiveOptic persp(mSW); - persp.setXFov(RAD2DEGF(focallength_to_fov(cam->lens, cam->sensor_x)), "xfov"); - persp.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio"); - persp.setZFar(cam->clip_end, false, "zfar"); - persp.setZNear(cam->clip_start, false, "znear"); - COLLADASW::Camera ccam(mSW, &persp, cam_id, cam_name); - exportBlenderProfile(ccam, cam); - addCamera(ccam); + switch (cam->type) { + case CAM_PANO: + case CAM_PERSP: { + COLLADASW::PerspectiveOptic persp(mSW); + persp.setXFov(RAD2DEGF(focallength_to_fov(cam->lens, cam->sensor_x)), "xfov"); + persp.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio"); + persp.setZFar(cam->clip_end, false, "zfar"); + persp.setZNear(cam->clip_start, false, "znear"); + COLLADASW::Camera ccam(mSW, &persp, cam_id, cam_name); + exportBlenderProfile(ccam, cam); + addCamera(ccam); - break; - } - case CAM_ORTHO: - default: - { - COLLADASW::OrthographicOptic ortho(mSW); - ortho.setXMag(cam->ortho_scale / 2, "xmag"); - ortho.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio"); - ortho.setZFar(cam->clip_end, false, "zfar"); - ortho.setZNear(cam->clip_start, false, "znear"); - COLLADASW::Camera ccam(mSW, &ortho, cam_id, cam_name); - exportBlenderProfile(ccam, cam); - addCamera(ccam); - break; - } - } + break; + } + case CAM_ORTHO: + default: { + COLLADASW::OrthographicOptic ortho(mSW); + ortho.setXMag(cam->ortho_scale / 2, "xmag"); + ortho.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio"); + ortho.setZFar(cam->clip_end, false, "zfar"); + ortho.setZNear(cam->clip_start, false, "znear"); + COLLADASW::Camera ccam(mSW, &ortho, cam_id, cam_name); + exportBlenderProfile(ccam, cam); + addCamera(ccam); + break; + } + } } -bool CamerasExporter::exportBlenderProfile(COLLADASW::Camera &cm,Camera *cam) +bool CamerasExporter::exportBlenderProfile(COLLADASW::Camera &cm, Camera *cam) { - cm.addExtraTechniqueParameter("blender","shiftx",cam->shiftx); - cm.addExtraTechniqueParameter("blender","shifty",cam->shifty); - cm.addExtraTechniqueParameter("blender","dof_distance",cam->dof_distance); - return true; - + cm.addExtraTechniqueParameter("blender", "shiftx", cam->shiftx); + cm.addExtraTechniqueParameter("blender", "shifty", cam->shifty); + cm.addExtraTechniqueParameter("blender", "dof_distance", cam->dof_distance); + return true; } diff --git a/source/blender/collada/CameraExporter.h b/source/blender/collada/CameraExporter.h index b421c8e7bf4..0a90fc017e8 100644 --- a/source/blender/collada/CameraExporter.h +++ b/source/blender/collada/CameraExporter.h @@ -32,15 +32,15 @@ extern "C" { #include "ExportSettings.h" #include "DNA_camera_types.h" -class CamerasExporter: COLLADASW::LibraryCameras -{ -public: - CamerasExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); - void exportCameras(Scene *sce); - void operator()(Object *ob, Scene *sce); -private: - bool exportBlenderProfile(COLLADASW::Camera &cla,Camera *cam); - const ExportSettings *export_settings; +class CamerasExporter : COLLADASW::LibraryCameras { + public: + CamerasExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); + void exportCameras(Scene *sce); + void operator()(Object *ob, Scene *sce); + + private: + bool exportBlenderProfile(COLLADASW::Camera &cla, Camera *cam); + const ExportSettings *export_settings; }; #endif diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 643280cb0cd..dc9a701192f 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -48,574 +48,596 @@ extern "C" { #include "collada_utils.h" - bool ControllerExporter::is_skinned_mesh(Object *ob) { - return bc_get_assigned_armature(ob) != NULL; + return bc_get_assigned_armature(ob) != NULL; } -void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) +void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, + Object *ob_arm, + Bone *bone) { - if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) { - std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name); - ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id)); - } - else { - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - write_bone_URLs(ins, ob_arm, child); - } - } + if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) { + std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name); + ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id)); + } + else { + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + write_bone_URLs(ins, ob_arm, child); + } + } } bool ControllerExporter::add_instance_controller(Object *ob) { - Object *ob_arm = bc_get_assigned_armature(ob); - bArmature *arm = (bArmature *)ob_arm->data; + Object *ob_arm = bc_get_assigned_armature(ob); + bArmature *arm = (bArmature *)ob_arm->data; - const std::string& controller_id = get_controller_id(ob_arm, ob); + const std::string &controller_id = get_controller_id(ob_arm, ob); - COLLADASW::InstanceController ins(mSW); - ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); + COLLADASW::InstanceController ins(mSW); + ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); - Mesh *me = (Mesh *)ob->data; - if (!me->dvert) return false; + Mesh *me = (Mesh *)ob->data; + if (!me->dvert) + return false; - // write root bone URLs - Bone *bone; - for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { - write_bone_URLs(ins, ob_arm, bone); - } + // write root bone URLs + Bone *bone; + for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { + write_bone_URLs(ins, ob_arm, bone); + } - InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings( + ins.getBindMaterial(), ob, this->export_settings->active_uv_only); - ins.add(); - return true; + ins.add(); + return true; } void ControllerExporter::export_controllers() { - Scene *sce = blender_context.get_scene(); - openLibrary(); + Scene *sce = blender_context.get_scene(); + openLibrary(); - GeometryFunctor gf; - gf.forEachMeshObjectInExportSet<ControllerExporter>(sce, *this, this->export_settings->export_set); + GeometryFunctor gf; + gf.forEachMeshObjectInExportSet<ControllerExporter>( + sce, *this, this->export_settings->export_set); - closeLibrary(); + closeLibrary(); } void ControllerExporter::operator()(Object *ob) { - Object *ob_arm = bc_get_assigned_armature(ob); - Key *key = BKE_key_from_object(ob); - - if (ob_arm) { - export_skin_controller(ob, ob_arm); - } - if (key && this->export_settings->include_shapekeys) { - export_morph_controller(ob, key); - } + Object *ob_arm = bc_get_assigned_armature(ob); + Key *key = BKE_key_from_object(ob); + + if (ob_arm) { + export_skin_controller(ob, ob_arm); + } + if (key && this->export_settings->include_shapekeys) { + export_morph_controller(ob, key); + } } #if 0 bool ArmatureExporter::already_written(Object *ob_arm) { - return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end(); + return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end(); } void ArmatureExporter::wrote(Object *ob_arm) { - written_armatures.push_back(ob_arm); + written_armatures.push_back(ob_arm); } void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce) { - objects.clear(); + objects.clear(); - Base *base = (Base *) sce->base.first; - while (base) { - Object *ob = base->object; + Base *base = (Base *) sce->base.first; + while (base) { + Object *ob = base->object; - if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) { - objects.push_back(ob); - } + if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) { + objects.push_back(ob); + } - base = base->next; - } + base = base->next; + } } #endif std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob) { - return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX; + return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + + SKIN_CONTROLLER_ID_SUFFIX; } std::string ControllerExporter::get_controller_id(Key *key, Object *ob) { - return translate_id(id_name(ob)) + MORPH_CONTROLLER_ID_SUFFIX; + return translate_id(id_name(ob)) + MORPH_CONTROLLER_ID_SUFFIX; } // ob should be of type OB_MESH // both args are required void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) { - // joint names - // joint inverse bind matrices - // vertex weights + // joint names + // joint inverse bind matrices + // vertex weights - // input: - // joint names: ob -> vertex group names - // vertex group weights: me->dvert -> groups -> index, weight + // input: + // joint names: ob -> vertex group names + // vertex group weights: me->dvert -> groups -> index, weight #if 0 - me->dvert : - - typedef struct MDeformVert { - struct MDeformWeight *dw; - int totweight; - int flag; // flag only in use for weightpaint now - } MDeformVert; - - typedef struct MDeformWeight { - int def_nr; - float weight; - } MDeformWeight; + me->dvert : + + typedef struct MDeformVert { + struct MDeformWeight *dw; + int totweight; + int flag; // flag only in use for weightpaint now + } MDeformVert; + + typedef struct MDeformWeight { + int def_nr; + float weight; + } MDeformWeight; #endif - bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me; - - if (((Mesh *)ob->data)->dvert == NULL) { - return; - } - - me = bc_get_mesh_copy( - blender_context, - ob, - this->export_settings->export_mesh_type, - this->export_settings->apply_modifiers, - this->export_settings->triangulate); - - std::string controller_name = id_name(ob_arm); - std::string controller_id = get_controller_id(ob_arm, ob); - - openSkin(controller_id, controller_name, - COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation))); - - add_bind_shape_mat(ob); - - std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id); - std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id); - - std::list<int> vcounts; - std::list<int> joints; - std::list<float> weights; - - { - int i, j; - - // def group index -> joint index - std::vector<int> joint_index_by_def_index; - bDeformGroup *def; - - for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) { - if (is_bone_defgroup(ob_arm, def)) - joint_index_by_def_index.push_back(j++); - else - joint_index_by_def_index.push_back(-1); - } - - int oob_counter = 0; - for (i = 0; i < me->totvert; i++) { - MDeformVert *vert = &me->dvert[i]; - std::map<int, float> jw; - - // We're normalizing the weights later - float sumw = 0.0f; - - for (j = 0; j < vert->totweight; j++) { - int idx = vert->dw[j].def_nr; - if (idx >= joint_index_by_def_index.size()) { - // XXX: Maybe better find out where and - // why the Out Of Bound indexes get created ? - oob_counter += 1; - } - else { - if (idx >= 0) { - int joint_index = joint_index_by_def_index[idx]; - if (joint_index != -1 && vert->dw[j].weight > 0.0f) { - jw[joint_index] += vert->dw[j].weight; - sumw += vert->dw[j].weight; - } - } - } - } - - if (sumw > 0.0f) { - float invsumw = 1.0f / sumw; - vcounts.push_back(jw.size()); - for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) { - joints.push_back((*m).first); - weights.push_back(invsumw * (*m).second); - } - } - else { - vcounts.push_back(0); + bool use_instantiation = this->export_settings->use_object_instantiation; + Mesh *me; + + if (((Mesh *)ob->data)->dvert == NULL) { + return; + } + + me = bc_get_mesh_copy(blender_context, + ob, + this->export_settings->export_mesh_type, + this->export_settings->apply_modifiers, + this->export_settings->triangulate); + + std::string controller_name = id_name(ob_arm); + std::string controller_id = get_controller_id(ob_arm, ob); + + openSkin(controller_id, + controller_name, + COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation))); + + add_bind_shape_mat(ob); + + std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id); + std::string inv_bind_mat_source_id = add_inv_bind_mats_source( + ob_arm, &ob->defbase, controller_id); + + std::list<int> vcounts; + std::list<int> joints; + std::list<float> weights; + + { + int i, j; + + // def group index -> joint index + std::vector<int> joint_index_by_def_index; + bDeformGroup *def; + + for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) { + if (is_bone_defgroup(ob_arm, def)) + joint_index_by_def_index.push_back(j++); + else + joint_index_by_def_index.push_back(-1); + } + + int oob_counter = 0; + for (i = 0; i < me->totvert; i++) { + MDeformVert *vert = &me->dvert[i]; + std::map<int, float> jw; + + // We're normalizing the weights later + float sumw = 0.0f; + + for (j = 0; j < vert->totweight; j++) { + int idx = vert->dw[j].def_nr; + if (idx >= joint_index_by_def_index.size()) { + // XXX: Maybe better find out where and + // why the Out Of Bound indexes get created ? + oob_counter += 1; + } + else { + if (idx >= 0) { + int joint_index = joint_index_by_def_index[idx]; + if (joint_index != -1 && vert->dw[j].weight > 0.0f) { + jw[joint_index] += vert->dw[j].weight; + sumw += vert->dw[j].weight; + } + } + } + } + + if (sumw > 0.0f) { + float invsumw = 1.0f / sumw; + vcounts.push_back(jw.size()); + for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) { + joints.push_back((*m).first); + weights.push_back(invsumw * (*m).second); + } + } + else { + vcounts.push_back(0); #if 0 - vcounts.push_back(1); - joints.push_back(-1); - weights.push_back(1.0f); + vcounts.push_back(1); + joints.push_back(-1); + weights.push_back(1.0f); #endif - } - } + } + } - if (oob_counter > 0) { - fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n", - oob_counter, joint_index_by_def_index.size()); - } - } + if (oob_counter > 0) { + fprintf(stderr, + "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n", + oob_counter, + joint_index_by_def_index.size()); + } + } - std::string weights_source_id = add_weights_source(me, controller_id, weights); - add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); - add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); + std::string weights_source_id = add_weights_source(me, controller_id, weights); + add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); + add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); - BKE_id_free(NULL, me); + BKE_id_free(NULL, me); - closeSkin(); - closeController(); + closeSkin(); + closeController(); } void ControllerExporter::export_morph_controller(Object *ob, Key *key) { - bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me; + bool use_instantiation = this->export_settings->use_object_instantiation; + Mesh *me; - me = bc_get_mesh_copy( - blender_context, - ob, - this->export_settings->export_mesh_type, - this->export_settings->apply_modifiers, - this->export_settings->triangulate); + me = bc_get_mesh_copy(blender_context, + ob, + this->export_settings->export_mesh_type, + this->export_settings->apply_modifiers, + this->export_settings->triangulate); - std::string controller_name = id_name(ob) + "-morph"; - std::string controller_id = get_controller_id(key, ob); + std::string controller_name = id_name(ob) + "-morph"; + std::string controller_id = get_controller_id(key, ob); - openMorph(controller_id, controller_name, - COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation))); + openMorph( + controller_id, + controller_name, + COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation))); - std::string targets_id = add_morph_targets(key, ob); - std::string morph_weights_id = add_morph_weights(key, ob); + std::string targets_id = add_morph_targets(key, ob); + std::string morph_weights_id = add_morph_weights(key, ob); - COLLADASW::TargetsElement targets(mSW); + COLLADASW::TargetsElement targets(mSW); - COLLADASW::InputList &input = targets.getInputList(); + COLLADASW::InputList &input = targets.getInputList(); - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_TARGET, // constant declared in COLLADASWInputList.h - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id))); - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT, - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id))); - targets.add(); + input.push_back(COLLADASW::Input( + COLLADASW::InputSemantic::MORPH_TARGET, // constant declared in COLLADASWInputList.h + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id))); + input.push_back( + COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT, + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id))); + targets.add(); - BKE_id_free(NULL, me); + BKE_id_free(NULL, me); - //support for animations - //can also try the base element and param alternative - add_weight_extras(key); - closeMorph(); - closeController(); + //support for animations + //can also try the base element and param alternative + add_weight_extras(key); + closeMorph(); + closeController(); } std::string ControllerExporter::add_morph_targets(Key *key, Object *ob) { - std::string source_id = translate_id(id_name(ob)) + TARGETS_SOURCE_ID_SUFFIX; - - COLLADASW::IdRefSource source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(key->totkey - 1); - source.setAccessorStride(1); + std::string source_id = translate_id(id_name(ob)) + TARGETS_SOURCE_ID_SUFFIX; - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("IDREF"); + COLLADASW::IdRefSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(key->totkey - 1); + source.setAccessorStride(1); - source.prepareToAppendValues(); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("IDREF"); - KeyBlock *kb = (KeyBlock *)key->block.first; - //skip the basis - kb = kb->next; - for (; kb; kb = kb->next) { - std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name); - source.appendValues(geom_id); + source.prepareToAppendValues(); - } + KeyBlock *kb = (KeyBlock *)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name); + source.appendValues(geom_id); + } - source.finish(); + source.finish(); - return source_id; + return source_id; } std::string ControllerExporter::add_morph_weights(Key *key, Object *ob) { - std::string source_id = translate_id(id_name(ob)) + WEIGHTS_SOURCE_ID_SUFFIX; + std::string source_id = translate_id(id_name(ob)) + WEIGHTS_SOURCE_ID_SUFFIX; - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(key->totkey - 1); - source.setAccessorStride(1); + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(key->totkey - 1); + source.setAccessorStride(1); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("MORPH_WEIGHT"); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("MORPH_WEIGHT"); - source.prepareToAppendValues(); + source.prepareToAppendValues(); - KeyBlock *kb = (KeyBlock *)key->block.first; - //skip the basis - kb = kb->next; - for (; kb; kb = kb->next) { - float weight = kb->curval; - source.appendValues(weight); - } - source.finish(); + KeyBlock *kb = (KeyBlock *)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + float weight = kb->curval; + source.appendValues(weight); + } + source.finish(); - return source_id; + return source_id; } //Added to implement support for animations. void ControllerExporter::add_weight_extras(Key *key) { - // can also try the base element and param alternative - COLLADASW::BaseExtraTechnique extra; - - KeyBlock *kb = (KeyBlock *)key->block.first; - //skip the basis - kb = kb->next; - for (; kb; kb = kb->next) { - // XXX why is the weight not used here and set to 0.0? - // float weight = kb->curval; - extra.addExtraTechniqueParameter ("KHR", "morph_weights" , 0.000, "MORPH_WEIGHT_TO_TARGET"); - } + // can also try the base element and param alternative + COLLADASW::BaseExtraTechnique extra; + + KeyBlock *kb = (KeyBlock *)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + // XXX why is the weight not used here and set to 0.0? + // float weight = kb->curval; + extra.addExtraTechniqueParameter("KHR", "morph_weights", 0.000, "MORPH_WEIGHT_TO_TARGET"); + } } - - void ControllerExporter::add_joints_element(ListBase *defbase, - const std::string& joints_source_id, const std::string& inv_bind_mat_source_id) + const std::string &joints_source_id, + const std::string &inv_bind_mat_source_id) { - COLLADASW::JointsElement joints(mSW); - COLLADASW::InputList &input = joints.getInputList(); - - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id))); - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX, - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id))); - joints.add(); + COLLADASW::JointsElement joints(mSW); + COLLADASW::InputList &input = joints.getInputList(); + + input.push_back(COLLADASW::Input( + COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id))); + input.push_back( + COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX, + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id))); + joints.add(); } void ControllerExporter::add_bind_shape_mat(Object *ob) { - double bind_mat[4][4]; - float f_obmat[4][4]; - BKE_object_matrix_local_get(ob, f_obmat); + double bind_mat[4][4]; + float f_obmat[4][4]; + BKE_object_matrix_local_get(ob, f_obmat); - //UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat); - UnitConverter::mat4_to_dae_double(bind_mat, f_obmat); - if (this->export_settings->limit_precision) - bc_sanitize_mat(bind_mat, LIMITTED_PRECISION); + //UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat); + UnitConverter::mat4_to_dae_double(bind_mat, f_obmat); + if (this->export_settings->limit_precision) + bc_sanitize_mat(bind_mat, LIMITTED_PRECISION); - addBindShapeTransform(bind_mat); + addBindShapeTransform(bind_mat); } -std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) +std::string ControllerExporter::add_joints_source(Object *ob_arm, + ListBase *defbase, + const std::string &controller_id) { - std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX; + std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX; - int totjoint = 0; - bDeformGroup *def; - for (def = (bDeformGroup *)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) - totjoint++; - } + int totjoint = 0; + bDeformGroup *def; + for (def = (bDeformGroup *)defbase->first; def; def = def->next) { + if (is_bone_defgroup(ob_arm, def)) + totjoint++; + } - COLLADASW::NameSource source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(totjoint); - source.setAccessorStride(1); + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(totjoint); + source.setAccessorStride(1); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("JOINT"); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("JOINT"); - source.prepareToAppendValues(); + source.prepareToAppendValues(); - for (def = (bDeformGroup *)defbase->first; def; def = def->next) { - Bone *bone = get_bone_from_defgroup(ob_arm, def); - if (bone) - source.appendValues(get_joint_sid(bone)); - } + for (def = (bDeformGroup *)defbase->first; def; def = def->next) { + Bone *bone = get_bone_from_defgroup(ob_arm, def); + if (bone) + source.appendValues(get_joint_sid(bone)); + } - source.finish(); + source.finish(); - return source_id; + return source_id; } - -std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) +std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, + ListBase *defbase, + const std::string &controller_id) { - std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX; + std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX; - int totjoint = 0; - for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) - totjoint++; - } + int totjoint = 0; + for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { + if (is_bone_defgroup(ob_arm, def)) + totjoint++; + } - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(totjoint); //BLI_listbase_count(defbase)); - source.setAccessorStride(16); + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(totjoint); //BLI_listbase_count(defbase)); + source.setAccessorStride(16); - source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("TRANSFORM"); + source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("TRANSFORM"); - source.prepareToAppendValues(); + source.prepareToAppendValues(); - bPose *pose = ob_arm->pose; - bArmature *arm = (bArmature *)ob_arm->data; + bPose *pose = ob_arm->pose; + bArmature *arm = (bArmature *)ob_arm->data; - int flag = arm->flag; + int flag = arm->flag; - // put armature in rest position - if (!(arm->flag & ARM_RESTPOS)) { - Depsgraph *depsgraph = blender_context.get_depsgraph(); - Scene *scene = blender_context.get_scene(); + // put armature in rest position + if (!(arm->flag & ARM_RESTPOS)) { + Depsgraph *depsgraph = blender_context.get_depsgraph(); + Scene *scene = blender_context.get_scene(); - arm->flag |= ARM_RESTPOS; - BKE_pose_where_is(depsgraph, scene, ob_arm); - } + arm->flag |= ARM_RESTPOS; + BKE_pose_where_is(depsgraph, scene, ob_arm); + } - for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) { - bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name); + for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { + if (is_bone_defgroup(ob_arm, def)) { + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name); - float mat[4][4]; - float world[4][4]; - float inv_bind_mat[4][4]; + float mat[4][4]; + float world[4][4]; + float inv_bind_mat[4][4]; - float bind_mat[4][4]; /* derived from bone->arm_mat */ + float bind_mat[4][4]; /* derived from bone->arm_mat */ - bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat); + bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat); - if (!has_bindmat) { + if (!has_bindmat) { - /* Have no bind matrix stored, try old style <= Blender 2.78 */ + /* Have no bind matrix stored, try old style <= Blender 2.78 */ - bc_create_restpose_mat(this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true); + bc_create_restpose_mat( + this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true); - // SL/OPEN_SIM COMPATIBILITY - if (export_settings->open_sim) { + // SL/OPEN_SIM COMPATIBILITY + if (export_settings->open_sim) { - float loc[3]; - float rot[3] = { 0, 0, 0 }; - float scale[3]; - bc_decompose(bind_mat, loc, NULL, NULL, scale); + float loc[3]; + float rot[3] = {0, 0, 0}; + float scale[3]; + bc_decompose(bind_mat, loc, NULL, NULL, scale); - // Only translations, no rotation vs armature - loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6); - } - } + // Only translations, no rotation vs armature + loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6); + } + } - // make world-space matrix (bind_mat is armature-space) - mul_m4_m4m4(world, ob_arm->obmat, bind_mat); + // make world-space matrix (bind_mat is armature-space) + mul_m4_m4m4(world, ob_arm->obmat, bind_mat); - invert_m4_m4(mat, world); - UnitConverter::mat4_to_dae(inv_bind_mat, mat); - if (this->export_settings->limit_precision) - bc_sanitize_mat(inv_bind_mat, LIMITTED_PRECISION); - source.appendValues(inv_bind_mat); - } - } + invert_m4_m4(mat, world); + UnitConverter::mat4_to_dae(inv_bind_mat, mat); + if (this->export_settings->limit_precision) + bc_sanitize_mat(inv_bind_mat, LIMITTED_PRECISION); + source.appendValues(inv_bind_mat); + } + } - // back from rest position - if (!(flag & ARM_RESTPOS)) { - Depsgraph *depsgraph = blender_context.get_depsgraph(); - Scene *scene = blender_context.get_scene(); - arm->flag = flag; - BKE_pose_where_is(depsgraph, scene, ob_arm); - } + // back from rest position + if (!(flag & ARM_RESTPOS)) { + Depsgraph *depsgraph = blender_context.get_depsgraph(); + Scene *scene = blender_context.get_scene(); + arm->flag = flag; + BKE_pose_where_is(depsgraph, scene, ob_arm); + } - source.finish(); + source.finish(); - return source_id; + return source_id; } Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name); - return pchan ? pchan->bone : NULL; + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name); + return pchan ? pchan->bone : NULL; } bool ControllerExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def) { - return get_bone_from_defgroup(ob_arm, def) != NULL; + return get_bone_from_defgroup(ob_arm, def) != NULL; } -std::string ControllerExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights) +std::string ControllerExporter::add_weights_source(Mesh *me, + const std::string &controller_id, + const std::list<float> &weights) { - std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX; + std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX; - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(weights.size()); - source.setAccessorStride(1); + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(weights.size()); + source.setAccessorStride(1); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("WEIGHT"); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("WEIGHT"); - source.prepareToAppendValues(); + source.prepareToAppendValues(); - for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) { - source.appendValues(*i); - } + for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) { + source.appendValues(*i); + } - source.finish(); + source.finish(); - return source_id; + return source_id; } -void ControllerExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, - const std::list<int>& vcounts, - const std::list<int>& joints) +void ControllerExporter::add_vertex_weights_element(const std::string &weights_source_id, + const std::string &joints_source_id, + const std::list<int> &vcounts, + const std::list<int> &joints) { - COLLADASW::VertexWeightsElement weightselem(mSW); - COLLADASW::InputList &input = weightselem.getInputList(); + COLLADASW::VertexWeightsElement weightselem(mSW); + COLLADASW::InputList &input = weightselem.getInputList(); - int offset = 0; - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++)); - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT, - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++)); + int offset = 0; + input.push_back(COLLADASW::Input( + COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), + offset++)); + input.push_back( + COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT, + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), + offset++)); - weightselem.setCount(vcounts.size()); + weightselem.setCount(vcounts.size()); - // write number of deformers per vertex - COLLADASW::PrimitivesBase::VCountList vcountlist; + // write number of deformers per vertex + COLLADASW::PrimitivesBase::VCountList vcountlist; - vcountlist.resize(vcounts.size()); - std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin()); + vcountlist.resize(vcounts.size()); + std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin()); - weightselem.prepareToAppendVCountValues(); - weightselem.appendVertexCount(vcountlist); + weightselem.prepareToAppendVCountValues(); + weightselem.appendVertexCount(vcountlist); - weightselem.CloseVCountAndOpenVElement(); + weightselem.CloseVCountAndOpenVElement(); - // write deformer index - weight index pairs - int weight_index = 0; - for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) { - weightselem.appendValues(*i, weight_index++); - } + // write deformer index - weight index pairs + int weight_index = 0; + for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) { + weightselem.appendValues(*i, weight_index++); + } - weightselem.finish(); + weightselem.finish(); } diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h index 31bb60bc3e6..50056df9f39 100644 --- a/source/blender/collada/ControllerExporter.h +++ b/source/blender/collada/ControllerExporter.h @@ -50,76 +50,88 @@ struct Depsgraph; class SceneExporter; -class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter -{ -public: - // XXX exporter writes wrong data for shared armatures. A separate - // controller should be written for each armature-mesh binding how do - // we make controller ids then? - ControllerExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : - COLLADASW::LibraryControllers(sw), - blender_context(blender_context), - export_settings(export_settings) { - } - - bool is_skinned_mesh(Object *ob); - - bool add_instance_controller(Object *ob); - - void export_controllers(); - - void operator()(Object *ob); - -private: - BlenderContext &blender_context; - const ExportSettings *export_settings; +class ControllerExporter : public COLLADASW::LibraryControllers, + protected TransformWriter, + protected InstanceWriter { + public: + // XXX exporter writes wrong data for shared armatures. A separate + // controller should be written for each armature-mesh binding how do + // we make controller ids then? + ControllerExporter(BlenderContext &blender_context, + COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings) + : COLLADASW::LibraryControllers(sw), + blender_context(blender_context), + export_settings(export_settings) + { + } + + bool is_skinned_mesh(Object *ob); + + bool add_instance_controller(Object *ob); + + void export_controllers(); + + void operator()(Object *ob); + + private: + BlenderContext &blender_context; + const ExportSettings *export_settings; #if 0 - std::vector<Object *> written_armatures; + std::vector<Object *> written_armatures; - bool already_written(Object *ob_arm); + bool already_written(Object *ob_arm); - void wrote(Object *ob_arm); + void wrote(Object *ob_arm); - void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); + void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); #endif - std::string get_controller_id(Object *ob_arm, Object *ob); + std::string get_controller_id(Object *ob_arm, Object *ob); - std::string get_controller_id(Key *key, Object *ob); + std::string get_controller_id(Key *key, Object *ob); - // ob should be of type OB_MESH - // both args are required - void export_skin_controller(Object *ob, Object *ob_arm); + // ob should be of type OB_MESH + // both args are required + void export_skin_controller(Object *ob, Object *ob_arm); - void export_morph_controller(Object *ob, Key *key); + void export_morph_controller(Object *ob, Key *key); - void add_joints_element(ListBase *defbase, - const std::string& joints_source_id, const std::string& inv_bind_mat_source_id); + void add_joints_element(ListBase *defbase, + const std::string &joints_source_id, + const std::string &inv_bind_mat_source_id); - void add_bind_shape_mat(Object *ob); + void add_bind_shape_mat(Object *ob); - std::string add_morph_targets(Key *key, Object *ob); + std::string add_morph_targets(Key *key, Object *ob); - std::string add_morph_weights(Key *key, Object *ob); + std::string add_morph_weights(Key *key, Object *ob); - void add_weight_extras(Key *key); + void add_weight_extras(Key *key); - std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id); + std::string add_joints_source(Object *ob_arm, + ListBase *defbase, + const std::string &controller_id); - std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id); + std::string add_inv_bind_mats_source(Object *ob_arm, + ListBase *defbase, + const std::string &controller_id); - Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def); + Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def); - bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def); + bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def); - std::string add_weights_source(Mesh *me, const std::string& controller_id, - const std::list<float>& weights); + std::string add_weights_source(Mesh *me, + const std::string &controller_id, + const std::list<float> &weights); - void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, - const std::list<int>& vcount, const std::list<int>& joints); + void add_vertex_weights_element(const std::string &weights_source_id, + const std::string &joints_source_id, + const std::list<int> &vcount, + const std::list<int> &joints); - void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone); + void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone); }; #endif diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 42056a7d984..71c0d6c155e 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -22,7 +22,7 @@ #include <stdio.h> #include <math.h> #include <vector> -#include <algorithm> // std::find +#include <algorithm> // std::find #include "COLLADASWCamera.h" #include "COLLADASWAsset.h" @@ -56,8 +56,7 @@ #include "COLLADASWInstanceNode.h" #include "COLLADASWBaseInputElement.h" -extern "C" -{ +extern "C" { #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_collection_types.h" @@ -79,7 +78,7 @@ extern "C" #include "BLI_listbase.h" #include "BLI_utildefines.h" -#include "BKE_action.h" // pose functions +#include "BKE_action.h" // pose functions #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_blender_version.h" @@ -130,44 +129,47 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype); char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n) { - int layer_index = CustomData_get_layer_index(data, type); - if (layer_index < 0) return NULL; + int layer_index = CustomData_get_layer_index(data, type); + if (layer_index < 0) + return NULL; - return data->layers[layer_index + n].name; + return data->layers[layer_index + n].name; } char *bc_CustomData_get_active_layer_name(const CustomData *data, int type) { - /* get the layer index of the active layer of type */ - int layer_index = CustomData_get_active_layer_index(data, type); - if (layer_index < 0) return NULL; + /* get the layer index of the active layer of type */ + int layer_index = CustomData_get_active_layer_index(data, type); + if (layer_index < 0) + return NULL; - return data->layers[layer_index].name; + return data->layers[layer_index].name; } -DocumentExporter::DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings) : - blender_context(blender_context), - export_settings(export_settings) { +DocumentExporter::DocumentExporter(BlenderContext &blender_context, + const ExportSettings *export_settings) + : blender_context(blender_context), export_settings(export_settings) +{ } static COLLADABU::NativeString make_temp_filepath(const char *name, const char *extension) { - char tempfile[FILE_MAX]; - const char *tempdir = BKE_tempdir_session(); + char tempfile[FILE_MAX]; + const char *tempdir = BKE_tempdir_session(); - if (name == NULL) { - name = "untitled"; - } + if (name == NULL) { + name = "untitled"; + } - BLI_make_file_string(NULL, tempfile, tempdir, name); + BLI_make_file_string(NULL, tempfile, tempdir, name); - if (extension) { - BLI_path_extension_ensure(tempfile, FILE_MAX, extension); - } + if (extension) { + BLI_path_extension_ensure(tempfile, FILE_MAX, extension); + } - COLLADABU::NativeString native_filename = - COLLADABU::NativeString(tempfile, COLLADABU::NativeString::ENCODING_UTF8); - return native_filename; + COLLADABU::NativeString native_filename = COLLADABU::NativeString( + tempfile, COLLADABU::NativeString::ENCODING_UTF8); + return native_filename; } // TODO: it would be better to instantiate animations rather than create a new one per object @@ -176,149 +178,157 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char * int DocumentExporter::exportCurrentScene() { - Scene *sce = blender_context.get_scene(); - bContext *C = blender_context.get_context(); - - PointerRNA sceneptr, unit_settings; - PropertyRNA *system; /* unused , *scale; */ - - clear_global_id_map(); - - COLLADABU::NativeString native_filename = make_temp_filepath(NULL, ".dae"); - COLLADASW::StreamWriter *writer = new COLLADASW::StreamWriter(native_filename); - - // open <collada> - writer->startDocument(); - - // <asset> - COLLADASW::Asset asset(writer); - - RNA_id_pointer_create(&(sce->id), &sceneptr); - unit_settings = RNA_pointer_get(&sceneptr, "unit_settings"); - system = RNA_struct_find_property(&unit_settings, "system"); - //scale = RNA_struct_find_property(&unit_settings, "scale_length"); - - std::string unitname = "meter"; - float linearmeasure = RNA_float_get(&unit_settings, "scale_length"); - - switch (RNA_property_enum_get(&unit_settings, system)) { - case USER_UNIT_NONE: - case USER_UNIT_METRIC: - if (linearmeasure == 0.001f) { - unitname = "millimeter"; - } - else if (linearmeasure == 0.01f) { - unitname = "centimeter"; - } - else if (linearmeasure == 0.1f) { - unitname = "decimeter"; - } - else if (linearmeasure == 1.0f) { - unitname = "meter"; - } - else if (linearmeasure == 1000.0f) { - unitname = "kilometer"; - } - break; - case USER_UNIT_IMPERIAL: - if (linearmeasure == 0.0254f) { - unitname = "inch"; - } - else if (linearmeasure == 0.3048f) { - unitname = "foot"; - } - else if (linearmeasure == 0.9144f) { - unitname = "yard"; - } - break; - default: - break; - } - - asset.setUnit(unitname, linearmeasure); - asset.setUpAxisType(COLLADASW::Asset::Z_UP); - asset.getContributor().mAuthor = "Blender User"; - char version_buf[128]; + Scene *sce = blender_context.get_scene(); + bContext *C = blender_context.get_context(); + + PointerRNA sceneptr, unit_settings; + PropertyRNA *system; /* unused , *scale; */ + + clear_global_id_map(); + + COLLADABU::NativeString native_filename = make_temp_filepath(NULL, ".dae"); + COLLADASW::StreamWriter *writer = new COLLADASW::StreamWriter(native_filename); + + // open <collada> + writer->startDocument(); + + // <asset> + COLLADASW::Asset asset(writer); + + RNA_id_pointer_create(&(sce->id), &sceneptr); + unit_settings = RNA_pointer_get(&sceneptr, "unit_settings"); + system = RNA_struct_find_property(&unit_settings, "system"); + //scale = RNA_struct_find_property(&unit_settings, "scale_length"); + + std::string unitname = "meter"; + float linearmeasure = RNA_float_get(&unit_settings, "scale_length"); + + switch (RNA_property_enum_get(&unit_settings, system)) { + case USER_UNIT_NONE: + case USER_UNIT_METRIC: + if (linearmeasure == 0.001f) { + unitname = "millimeter"; + } + else if (linearmeasure == 0.01f) { + unitname = "centimeter"; + } + else if (linearmeasure == 0.1f) { + unitname = "decimeter"; + } + else if (linearmeasure == 1.0f) { + unitname = "meter"; + } + else if (linearmeasure == 1000.0f) { + unitname = "kilometer"; + } + break; + case USER_UNIT_IMPERIAL: + if (linearmeasure == 0.0254f) { + unitname = "inch"; + } + else if (linearmeasure == 0.3048f) { + unitname = "foot"; + } + else if (linearmeasure == 0.9144f) { + unitname = "yard"; + } + break; + default: + break; + } + + asset.setUnit(unitname, linearmeasure); + asset.setUpAxisType(COLLADASW::Asset::Z_UP); + asset.getContributor().mAuthor = "Blender User"; + char version_buf[128]; #ifdef WITH_BUILDINFO - BLI_snprintf(version_buf, sizeof(version_buf), "Blender %d.%02d.%d commit date:%s, commit time:%s, hash:%s", - BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION, - build_commit_date, build_commit_time, build_hash); + BLI_snprintf(version_buf, + sizeof(version_buf), + "Blender %d.%02d.%d commit date:%s, commit time:%s, hash:%s", + BLENDER_VERSION / 100, + BLENDER_VERSION % 100, + BLENDER_SUBVERSION, + build_commit_date, + build_commit_time, + build_hash); #else - BLI_snprintf(version_buf, sizeof(version_buf), "Blender %d.%02d.%d", - BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION); + BLI_snprintf(version_buf, + sizeof(version_buf), + "Blender %d.%02d.%d", + BLENDER_VERSION / 100, + BLENDER_VERSION % 100, + BLENDER_SUBVERSION); #endif - asset.getContributor().mAuthoringTool = version_buf; - asset.add(); - - LinkNode *export_set = this->export_settings->export_set; - // <library_cameras> - if (bc_has_object_type(export_set, OB_CAMERA)) { - CamerasExporter ce(writer, this->export_settings); - ce.exportCameras(sce); - } - - // <library_lights> - if (bc_has_object_type(export_set, OB_LAMP)) { - LightsExporter le(writer, this->export_settings); - le.exportLights(sce); - } - - // <library_effects> - EffectsExporter ee(writer, this->export_settings, key_image_map); - ee.exportEffects(C, sce); - - // <library_images> - ImagesExporter ie(writer, this->export_settings, key_image_map); - ie.exportImages(sce); - - // <library_materials> - MaterialsExporter me(writer, this->export_settings); - me.exportMaterials(sce); - - // <library_geometries> - if (bc_has_object_type(export_set, OB_MESH)) { - GeometryExporter ge(blender_context, writer, this->export_settings); - ge.exportGeom(); - } - - // <library_controllers> - ArmatureExporter arm_exporter(blender_context, writer, this->export_settings); - ControllerExporter controller_exporter(blender_context, writer, this->export_settings); - if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys) - { - controller_exporter.export_controllers(); - } - - // <library_visual_scenes> - - SceneExporter se(blender_context, writer, &arm_exporter, this->export_settings); - - if (this->export_settings->include_animations) { - // <library_animations> - AnimationExporter ae(blender_context, writer, this->export_settings); - ae.exportAnimations(); - } - - se.exportScene(); - - // <scene> - std::string scene_name(translate_id(id_name(sce))); - COLLADASW::Scene scene(writer, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, - scene_name)); - scene.add(); - - // close <Collada> - writer->endDocument(); - delete writer; - - // Finally move the created document into place - fprintf(stdout, "Collada export to: %s\n", this->export_settings->filepath); - int status = BLI_rename(native_filename.c_str(), this->export_settings->filepath); - if (status != 0) { - status = BLI_copy(native_filename.c_str(), this->export_settings->filepath); - BLI_delete(native_filename.c_str(), false, false); - } - return status; + asset.getContributor().mAuthoringTool = version_buf; + asset.add(); + + LinkNode *export_set = this->export_settings->export_set; + // <library_cameras> + if (bc_has_object_type(export_set, OB_CAMERA)) { + CamerasExporter ce(writer, this->export_settings); + ce.exportCameras(sce); + } + + // <library_lights> + if (bc_has_object_type(export_set, OB_LAMP)) { + LightsExporter le(writer, this->export_settings); + le.exportLights(sce); + } + + // <library_effects> + EffectsExporter ee(writer, this->export_settings, key_image_map); + ee.exportEffects(C, sce); + + // <library_images> + ImagesExporter ie(writer, this->export_settings, key_image_map); + ie.exportImages(sce); + + // <library_materials> + MaterialsExporter me(writer, this->export_settings); + me.exportMaterials(sce); + + // <library_geometries> + if (bc_has_object_type(export_set, OB_MESH)) { + GeometryExporter ge(blender_context, writer, this->export_settings); + ge.exportGeom(); + } + + // <library_controllers> + ArmatureExporter arm_exporter(blender_context, writer, this->export_settings); + ControllerExporter controller_exporter(blender_context, writer, this->export_settings); + if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys) { + controller_exporter.export_controllers(); + } + + // <library_visual_scenes> + + SceneExporter se(blender_context, writer, &arm_exporter, this->export_settings); + + if (this->export_settings->include_animations) { + // <library_animations> + AnimationExporter ae(blender_context, writer, this->export_settings); + ae.exportAnimations(); + } + + se.exportScene(); + + // <scene> + std::string scene_name(translate_id(id_name(sce))); + COLLADASW::Scene scene(writer, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, scene_name)); + scene.add(); + + // close <Collada> + writer->endDocument(); + delete writer; + + // Finally move the created document into place + fprintf(stdout, "Collada export to: %s\n", this->export_settings->filepath); + int status = BLI_rename(native_filename.c_str(), this->export_settings->filepath); + if (status != 0) { + status = BLI_copy(native_filename.c_str(), this->export_settings->filepath); + BLI_delete(native_filename.c_str(), false, false); + } + return status; } void DocumentExporter::exportScenes(const char *filename) diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h index 203c77ed7ab..a5608d13a71 100644 --- a/source/blender/collada/DocumentExporter.h +++ b/source/blender/collada/DocumentExporter.h @@ -27,19 +27,18 @@ extern "C" { #include "DNA_customdata_types.h" - } -class DocumentExporter -{ +class DocumentExporter { public: - DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings); - int exportCurrentScene(); - void exportScenes(const char *filename); -private: - BlenderContext &blender_context; - const ExportSettings *export_settings; - KeyImageMap key_image_map; + DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings); + int exportCurrentScene(); + void exportScenes(const char *filename); + + private: + BlenderContext &blender_context; + const ExportSettings *export_settings; + KeyImageMap key_image_map; }; #endif diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index f784c811c26..d21e71bb37b 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -24,7 +24,7 @@ #include <string> #include <map> -#include <algorithm> // sort() +#include <algorithm> // sort() #include "COLLADAFWRoot.h" #include "COLLADAFWStableHeaders.h" @@ -72,7 +72,6 @@ extern "C" { #include "WM_api.h" #include "WM_types.h" - } #include "DEG_depsgraph.h" @@ -96,76 +95,82 @@ extern "C" { // creates empties for each imported bone on layer 2, for debugging // #define ARMATURE_TEST -DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) : - import_settings(import_settings), - mImportStage(Fetching_Scene_data), - mContext(C), - view_layer(CTX_data_view_layer(mContext)), - armature_importer(&unit_converter, &mesh_importer, CTX_data_main(C), CTX_data_scene(C), view_layer, import_settings), - mesh_importer(&unit_converter, &armature_importer, CTX_data_main(C), CTX_data_scene(C), view_layer), - anim_importer(C, &unit_converter, &armature_importer, CTX_data_scene(C)) +DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) + : import_settings(import_settings), + mImportStage(Fetching_Scene_data), + mContext(C), + view_layer(CTX_data_view_layer(mContext)), + armature_importer(&unit_converter, + &mesh_importer, + CTX_data_main(C), + CTX_data_scene(C), + view_layer, + import_settings), + mesh_importer( + &unit_converter, &armature_importer, CTX_data_main(C), CTX_data_scene(C), view_layer), + anim_importer(C, &unit_converter, &armature_importer, CTX_data_scene(C)) { } DocumentImporter::~DocumentImporter() { - TagsMap::iterator etit; - etit = uid_tags_map.begin(); - while (etit != uid_tags_map.end()) { - delete etit->second; - etit++; - } + TagsMap::iterator etit; + etit = uid_tags_map.begin(); + while (etit != uid_tags_map.end()) { + delete etit->second; + etit++; + } } bool DocumentImporter::import() { - ErrorHandler errorHandler; - COLLADASaxFWL::Loader loader(&errorHandler); - COLLADAFW::Root root(&loader, this); - ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer)); - - loader.registerExtraDataCallbackHandler(ehandler); - - // deselect all to select new objects - BKE_view_layer_base_deselect_all(view_layer); - - std::string mFilename = std::string(this->import_settings->filepath); - const std::string encodedFilename = bc_url_encode(mFilename); - if (!root.loadDocument(encodedFilename)) { - fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n"); - delete ehandler; - return false; - } - - if (errorHandler.hasError()) { - delete ehandler; - return false; - } - - /** TODO set up scene graph and such here */ - mImportStage = Fetching_Controller_data; - COLLADASaxFWL::Loader loader2; - COLLADAFW::Root root2(&loader2, this); - - if (!root2.loadDocument(encodedFilename)) { - fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n"); - delete ehandler; - return false; - } - - delete ehandler; - - return true; + ErrorHandler errorHandler; + COLLADASaxFWL::Loader loader(&errorHandler); + COLLADAFW::Root root(&loader, this); + ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer)); + + loader.registerExtraDataCallbackHandler(ehandler); + + // deselect all to select new objects + BKE_view_layer_base_deselect_all(view_layer); + + std::string mFilename = std::string(this->import_settings->filepath); + const std::string encodedFilename = bc_url_encode(mFilename); + if (!root.loadDocument(encodedFilename)) { + fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n"); + delete ehandler; + return false; + } + + if (errorHandler.hasError()) { + delete ehandler; + return false; + } + + /** TODO set up scene graph and such here */ + mImportStage = Fetching_Controller_data; + COLLADASaxFWL::Loader loader2; + COLLADAFW::Root root2(&loader2, this); + + if (!root2.loadDocument(encodedFilename)) { + fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n"); + delete ehandler; + return false; + } + + delete ehandler; + + return true; } -void DocumentImporter::cancel(const COLLADAFW::String& errorMessage) +void DocumentImporter::cancel(const COLLADAFW::String &errorMessage) { - // TODO: if possible show error info - // - // Should we get rid of invisible Meshes that were created so far - // or maybe create objects at coordinate space origin? - // - // The latter sounds better. + // TODO: if possible show error info + // + // Should we get rid of invisible Meshes that were created so far + // or maybe create objects at coordinate space origin? + // + // The latter sounds better. } void DocumentImporter::start() @@ -174,143 +179,145 @@ void DocumentImporter::start() void DocumentImporter::finish() { - if (mImportStage == Fetching_Controller_data) - return; - - Main *bmain = CTX_data_main(mContext); - // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it - Scene *sce = CTX_data_scene(mContext); - unit_converter.calculate_scale(*sce); - - std::vector<Object *> *objects_to_scale = new std::vector<Object *>(); - - /** TODO Break up and put into 2-pass parsing of DAE */ - std::vector<const COLLADAFW::VisualScene *>::iterator sit; - for (sit = vscenes.begin(); sit != vscenes.end(); sit++) { - PointerRNA sceneptr, unit_settings; - PropertyRNA *system, *scale; - - // for scene unit settings: system, scale_length - - RNA_id_pointer_create(&sce->id, &sceneptr); - unit_settings = RNA_pointer_get(&sceneptr, "unit_settings"); - system = RNA_struct_find_property(&unit_settings, "system"); - scale = RNA_struct_find_property(&unit_settings, "scale_length"); - - if (this->import_settings->import_units) { - - switch (unit_converter.isMetricSystem()) { - case UnitConverter::Metric: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC); - break; - case UnitConverter::Imperial: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL); - break; - default: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE); - break; - } - float unit_factor = unit_converter.getLinearMeter(); - RNA_property_float_set(&unit_settings, scale, unit_factor); - fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor); - - } - - // Write nodes to scene - fprintf(stderr, "+-- Import Scene --------\n"); - const COLLADAFW::NodePointerArray& roots = (*sit)->getRootNodes(); - for (unsigned int i = 0; i < roots.getCount(); i++) { - std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false); - objects_to_scale->insert(objects_to_scale->end(), objects_done->begin(), objects_done->end()); - delete objects_done; - } - - } - - - mesh_importer.optimize_material_assignements(); - - armature_importer.set_tags_map(this->uid_tags_map); - armature_importer.make_armatures(mContext, *objects_to_scale); - armature_importer.make_shape_keys(mContext); + if (mImportStage == Fetching_Controller_data) + return; + + Main *bmain = CTX_data_main(mContext); + // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it + Scene *sce = CTX_data_scene(mContext); + unit_converter.calculate_scale(*sce); + + std::vector<Object *> *objects_to_scale = new std::vector<Object *>(); + + /** TODO Break up and put into 2-pass parsing of DAE */ + std::vector<const COLLADAFW::VisualScene *>::iterator sit; + for (sit = vscenes.begin(); sit != vscenes.end(); sit++) { + PointerRNA sceneptr, unit_settings; + PropertyRNA *system, *scale; + + // for scene unit settings: system, scale_length + + RNA_id_pointer_create(&sce->id, &sceneptr); + unit_settings = RNA_pointer_get(&sceneptr, "unit_settings"); + system = RNA_struct_find_property(&unit_settings, "system"); + scale = RNA_struct_find_property(&unit_settings, "scale_length"); + + if (this->import_settings->import_units) { + + switch (unit_converter.isMetricSystem()) { + case UnitConverter::Metric: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC); + break; + case UnitConverter::Imperial: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL); + break; + default: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE); + break; + } + float unit_factor = unit_converter.getLinearMeter(); + RNA_property_float_set(&unit_settings, scale, unit_factor); + fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor); + } + + // Write nodes to scene + fprintf(stderr, "+-- Import Scene --------\n"); + const COLLADAFW::NodePointerArray &roots = (*sit)->getRootNodes(); + for (unsigned int i = 0; i < roots.getCount(); i++) { + std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false); + objects_to_scale->insert( + objects_to_scale->end(), objects_done->begin(), objects_done->end()); + delete objects_done; + } + } + + mesh_importer.optimize_material_assignements(); + + armature_importer.set_tags_map(this->uid_tags_map); + armature_importer.make_armatures(mContext, *objects_to_scale); + armature_importer.make_shape_keys(mContext); #if 0 - armature_importer.fix_animation(); + armature_importer.fix_animation(); #endif - for (std::vector<const COLLADAFW::VisualScene *>::iterator vsit = vscenes.begin(); vsit != vscenes.end(); vsit++) { - const COLLADAFW::NodePointerArray& roots = (*vsit)->getRootNodes(); + for (std::vector<const COLLADAFW::VisualScene *>::iterator vsit = vscenes.begin(); + vsit != vscenes.end(); + vsit++) { + const COLLADAFW::NodePointerArray &roots = (*vsit)->getRootNodes(); - for (unsigned int i = 0; i < roots.getCount(); i++) { - translate_anim_recursive(roots[i], NULL, NULL); - } - } + for (unsigned int i = 0; i < roots.getCount(); i++) { + translate_anim_recursive(roots[i], NULL, NULL); + } + } - if (libnode_ob.size()) { + if (libnode_ob.size()) { - fprintf(stderr, "| Cleanup: free %d library nodes\n", (int)libnode_ob.size()); - // free all library_nodes - std::vector<Object *>::iterator it; - for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { - Object *ob = *it; - BKE_scene_collections_object_remove(bmain, sce, ob, true); - } - libnode_ob.clear(); - } + fprintf(stderr, "| Cleanup: free %d library nodes\n", (int)libnode_ob.size()); + // free all library_nodes + std::vector<Object *>::iterator it; + for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { + Object *ob = *it; + BKE_scene_collections_object_remove(bmain, sce, ob, true); + } + libnode_ob.clear(); + } - bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units); + bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units); - delete objects_to_scale; + delete objects_to_scale; - // update scene - DEG_id_tag_update(&sce->id, ID_RECALC_COPY_ON_WRITE); - DEG_relations_tag_update(bmain); - WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL); + // update scene + DEG_id_tag_update(&sce->id, ID_RECALC_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL); } - -void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL) +void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, + COLLADAFW::Node *par = NULL, + Object *parob = NULL) { - // The split in #29246, rootmap must point at actual root when - // calculating bones in apply_curves_as_matrix. - actual root is the root node. - // This has to do with inverse bind poses being world space - // (the sources for skinned bones' restposes) and the way - // non-skinning nodes have their "restpose" recursively calculated. - // XXX TODO: design issue, how to support unrelated joints taking - // part in skinning. - if (par) { // && par->getType() == COLLADAFW::Node::JOINT) { - // par is root if there's no corresp. key in root_map - if (root_map.find(par->getUniqueId()) == root_map.end()) - root_map[node->getUniqueId()] = node; - else - root_map[node->getUniqueId()] = root_map[par->getUniqueId()]; - } + // The split in #29246, rootmap must point at actual root when + // calculating bones in apply_curves_as_matrix. - actual root is the root node. + // This has to do with inverse bind poses being world space + // (the sources for skinned bones' restposes) and the way + // non-skinning nodes have their "restpose" recursively calculated. + // XXX TODO: design issue, how to support unrelated joints taking + // part in skinning. + if (par) { // && par->getType() == COLLADAFW::Node::JOINT) { + // par is root if there's no corresp. key in root_map + if (root_map.find(par->getUniqueId()) == root_map.end()) + root_map[node->getUniqueId()] = node; + else + root_map[node->getUniqueId()] = root_map[par->getUniqueId()]; + } #if 0 - COLLADAFW::Transformation::TransformationType types[] = { - COLLADAFW::Transformation::ROTATE, - COLLADAFW::Transformation::SCALE, - COLLADAFW::Transformation::TRANSLATE, - COLLADAFW::Transformation::MATRIX, - }; - - Object *ob; + COLLADAFW::Transformation::TransformationType types[] = { + COLLADAFW::Transformation::ROTATE, + COLLADAFW::Transformation::SCALE, + COLLADAFW::Transformation::TRANSLATE, + COLLADAFW::Transformation::MATRIX, + }; + + Object *ob; #endif - unsigned int i; - - if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) { - // For Skeletons without root node we have to simulate the - // root node here and recursively enter the same function - // XXX: maybe this can be made more elegant. - translate_anim_recursive(node, node, parob); - } - else { - anim_importer.translate_Animations(node, root_map, object_map, FW_object_map, uid_material_map); - COLLADAFW::NodePointerArray &children = node->getChildNodes(); - for (i = 0; i < children.getCount(); i++) { - translate_anim_recursive(children[i], node, NULL); - } - } + unsigned int i; + + if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) { + // For Skeletons without root node we have to simulate the + // root node here and recursively enter the same function + // XXX: maybe this can be made more elegant. + translate_anim_recursive(node, node, parob); + } + else { + anim_importer.translate_Animations( + node, root_map, object_map, FW_object_map, uid_material_map); + COLLADAFW::NodePointerArray &children = node->getChildNodes(); + for (i = 0; i < children.getCount(); i++) { + translate_anim_recursive(children[i], node, NULL); + } + } } /** @@ -319,373 +326,384 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW */ std::string DocumentImporter::get_import_version(const COLLADAFW::FileInfo *asset) { - const char AUTORING_TOOL[] = "authoring_tool"; - const std::string BLENDER("Blender "); - const COLLADAFW::FileInfo::ValuePairPointerArray &valuePairs = asset->getValuePairArray(); - for ( size_t i = 0, count = valuePairs.getCount(); i < count; ++i) - { - const COLLADAFW::FileInfo::ValuePair* valuePair = valuePairs[i]; - const COLLADAFW::String& key = valuePair->first; - const COLLADAFW::String& value = valuePair->second; - if ( key == AUTORING_TOOL ) - { - if (value.compare(0, BLENDER.length(), BLENDER) == 0) - { - // Was made with Blender, now get version string - std::string v = value.substr(BLENDER.length()); - std::string::size_type n = v.find(" "); - if (n > 0) { - return v.substr(0,n); - } - } - } - } - return ""; + const char AUTORING_TOOL[] = "authoring_tool"; + const std::string BLENDER("Blender "); + const COLLADAFW::FileInfo::ValuePairPointerArray &valuePairs = asset->getValuePairArray(); + for (size_t i = 0, count = valuePairs.getCount(); i < count; ++i) { + const COLLADAFW::FileInfo::ValuePair *valuePair = valuePairs[i]; + const COLLADAFW::String &key = valuePair->first; + const COLLADAFW::String &value = valuePair->second; + if (key == AUTORING_TOOL) { + if (value.compare(0, BLENDER.length(), BLENDER) == 0) { + // Was made with Blender, now get version string + std::string v = value.substr(BLENDER.length()); + std::string::size_type n = v.find(" "); + if (n > 0) { + return v.substr(0, n); + } + } + } + } + return ""; } /** When this method is called, the writer must write the global document asset. * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeGlobalAsset(const COLLADAFW::FileInfo *asset) { - unit_converter.read_asset(asset); - import_from_version = get_import_version(asset); - anim_importer.set_import_from_version(import_from_version); - return true; + unit_converter.read_asset(asset); + import_from_version = get_import_version(asset); + anim_importer.set_import_from_version(import_from_version); + return true; } /** When this method is called, the writer must write the scene. * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeScene(const COLLADAFW::Scene *scene) { - // XXX could store the scene id, but do nothing for now - return true; + // XXX could store the scene id, but do nothing for now + return true; } Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce) { - const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId(); - if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) { - // fprintf(stderr, "Couldn't find camera by UID.\n"); - return NULL; - } - - Main *bmain = CTX_data_main(mContext); - Object *ob = bc_add_object(bmain, sce, view_layer, OB_CAMERA, NULL); - Camera *cam = uid_camera_map[cam_uid]; - Camera *old_cam = (Camera *)ob->data; - ob->data = cam; - BKE_id_free_us(bmain, old_cam); - return ob; + const COLLADAFW::UniqueId &cam_uid = camera->getInstanciatedObjectId(); + if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) { + // fprintf(stderr, "Couldn't find camera by UID.\n"); + return NULL; + } + + Main *bmain = CTX_data_main(mContext); + Object *ob = bc_add_object(bmain, sce, view_layer, OB_CAMERA, NULL); + Camera *cam = uid_camera_map[cam_uid]; + Camera *old_cam = (Camera *)ob->data; + ob->data = cam; + BKE_id_free_us(bmain, old_cam); + return ob; } Object *DocumentImporter::create_light_object(COLLADAFW::InstanceLight *lamp, Scene *sce) { - const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId(); - if (uid_light_map.find(lamp_uid) == uid_light_map.end()) { - fprintf(stderr, "Couldn't find light by UID.\n"); - return NULL; - } - - Main *bmain = CTX_data_main(mContext); - Object *ob = bc_add_object(bmain, sce, view_layer, OB_LAMP, NULL); - Light *la = uid_light_map[lamp_uid]; - Light *old_light = (Light *)ob->data; - ob->data = la; - BKE_id_free_us(bmain, old_light); - return ob; + const COLLADAFW::UniqueId &lamp_uid = lamp->getInstanciatedObjectId(); + if (uid_light_map.find(lamp_uid) == uid_light_map.end()) { + fprintf(stderr, "Couldn't find light by UID.\n"); + return NULL; + } + + Main *bmain = CTX_data_main(mContext); + Object *ob = bc_add_object(bmain, sce, view_layer, OB_LAMP, NULL); + Light *la = uid_light_map[lamp_uid]; + Light *old_light = (Light *)ob->data; + ob->data = la; + BKE_id_free_us(bmain, old_light); + return ob; } -Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node) +Object *DocumentImporter::create_instance_node(Object *source_ob, + COLLADAFW::Node *source_node, + COLLADAFW::Node *instance_node, + Scene *sce, + bool is_library_node) { - //fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL); - - Main *bmain = CTX_data_main(mContext); - Object *obn = BKE_object_copy(bmain, source_ob); - DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); - BKE_collection_object_add_from(bmain, sce, source_ob, obn); - - if (instance_node) { - anim_importer.read_node_transform(instance_node, obn); - // if we also have a source_node (always ;), take its - // transformation matrix and apply it to the newly instantiated - // object to account for node hierarchy transforms in - // .dae - if (source_node) { - COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix(); - COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order - float mat[4][4]; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - mat[i][j] = bmat4[i][j]; - } - } - // calc new matrix and apply - mul_m4_m4m4(obn->obmat, obn->obmat, mat); - BKE_object_apply_mat4(obn, obn->obmat, 0, 0); - } - } - else { - anim_importer.read_node_transform(source_node, obn); - } - - /*DAG_relations_tag_update(CTX_data_main(mContext));*/ - - COLLADAFW::NodePointerArray &children = source_node->getChildNodes(); - if (children.getCount()) { - for (unsigned int i = 0; i < children.getCount(); i++) { - COLLADAFW::Node *child_node = children[i]; - const COLLADAFW::UniqueId& child_id = child_node->getUniqueId(); - if (object_map.find(child_id) == object_map.end()) - continue; - COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes(); - Object *new_child = NULL; - if (inodes.getCount()) { // \todo loop through instance nodes - const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId(); - fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id)); - new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node); - } - else { - new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node); - } - bc_set_parent(new_child, obn, mContext, true); - - if (is_library_node) - libnode_ob.push_back(new_child); - } - } - - return obn; + //fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL); + + Main *bmain = CTX_data_main(mContext); + Object *obn = BKE_object_copy(bmain, source_ob); + DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + BKE_collection_object_add_from(bmain, sce, source_ob, obn); + + if (instance_node) { + anim_importer.read_node_transform(instance_node, obn); + // if we also have a source_node (always ;), take its + // transformation matrix and apply it to the newly instantiated + // object to account for node hierarchy transforms in + // .dae + if (source_node) { + COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix(); + COLLADABU::Math::Matrix4 bmat4 = + mat4.transpose(); // transpose to get blender row-major order + float mat[4][4]; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + mat[i][j] = bmat4[i][j]; + } + } + // calc new matrix and apply + mul_m4_m4m4(obn->obmat, obn->obmat, mat); + BKE_object_apply_mat4(obn, obn->obmat, 0, 0); + } + } + else { + anim_importer.read_node_transform(source_node, obn); + } + + /*DAG_relations_tag_update(CTX_data_main(mContext));*/ + + COLLADAFW::NodePointerArray &children = source_node->getChildNodes(); + if (children.getCount()) { + for (unsigned int i = 0; i < children.getCount(); i++) { + COLLADAFW::Node *child_node = children[i]; + const COLLADAFW::UniqueId &child_id = child_node->getUniqueId(); + if (object_map.find(child_id) == object_map.end()) + continue; + COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes(); + Object *new_child = NULL; + if (inodes.getCount()) { // \todo loop through instance nodes + const COLLADAFW::UniqueId &id = inodes[0]->getInstanciatedObjectId(); + fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id)); + new_child = create_instance_node( + object_map.find(id)->second, node_map[id], child_node, sce, is_library_node); + } + else { + new_child = create_instance_node( + object_map.find(child_id)->second, child_node, NULL, sce, is_library_node); + } + bc_set_parent(new_child, obn, mContext, true); + + if (is_library_node) + libnode_ob.push_back(new_child); + } + } + + return obn; } // to create constraints off node <extra> tags. Assumes only constraint data in // current <extra> with blender profile. void DocumentImporter::create_constraints(ExtraTags *et, Object *ob) { - if (et && et->isProfile("blender")) { - std::string name; - short type = 0; - et->setData("type", &type); - BKE_constraint_add_for_object(ob, "Test_con", type); - - } + if (et && et->isProfile("blender")) { + std::string name; + short type = 0; + et->setData("type", &type); + BKE_constraint_add_for_object(ob, "Test_con", type); + } } -void DocumentImporter::report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type) +void DocumentImporter::report_unknown_reference(const COLLADAFW::Node &node, + const std::string object_type) { - std::string id = node.getOriginalId(); - std::string name = node.getName(); - fprintf(stderr, - "error: node id=\"%s\", name=\"%s\" refers to an undefined %s.\n", - id.c_str(), - name.c_str(), - object_type.c_str()); + std::string id = node.getOriginalId(); + std::string name = node.getName(); + fprintf(stderr, + "error: node id=\"%s\", name=\"%s\" refers to an undefined %s.\n", + id.c_str(), + name.c_str(), + object_type.c_str()); } -std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) +std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, + COLLADAFW::Node *parent_node, + Scene *sce, + Object *par, + bool is_library_node) { - Main *bmain = CTX_data_main(mContext); - Object *ob = NULL; - bool is_joint = node->getType() == COLLADAFW::Node::JOINT; - bool read_transform = true; - std::string id = node->getOriginalId(); - std::string name = node->getName(); - - // if node has child nodes write them - COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); - - std::vector<Object *> *objects_done = new std::vector<Object *>(); - std::vector<Object *> *root_objects = new std::vector<Object *>(); - - fprintf(stderr, - "| %s id='%s', name='%s'\n", - is_joint ? "JOINT" : "NODE ", - id.c_str(), - name.c_str() ); - - if (is_joint) { - if (parent_node == NULL && !is_library_node) { - // A Joint on root level is a skeleton without root node. - // Here we add the armature "on the fly": - par = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, std::string("Armature").c_str()); - objects_done->push_back(par); - root_objects->push_back(par); - object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par)); - node_map[node->getUniqueId()] = node; - } - if (parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT) { - armature_importer.add_root_joint(node, par); - } - - if (parent_node == NULL) { - // for skeletons without root node all has been done above. - // Skeletons with root node are handled further down. - goto finally; - } - } - else { - COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries(); - COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras(); - COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights(); - COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers(); - COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes(); - size_t geom_done = 0; - size_t camera_done = 0; - size_t lamp_done = 0; - size_t controller_done = 0; - size_t inst_done = 0; - - // XXX linking object with the first <instance_geometry>, though a node may have more of them... - // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure... - // <instance_geometry> - while (geom_done < geom.getCount()) { - ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map); - if (ob == NULL) { - report_unknown_reference(*node, "instance_mesh"); - } - else { - objects_done->push_back(ob); - if (parent_node == NULL) { - root_objects->push_back(ob); - } - } - ++geom_done; - } - while (camera_done < camera.getCount()) { - ob = create_camera_object(camera[camera_done], sce); - if (ob == NULL) { - report_unknown_reference(*node, "instance_camera"); - } - else { - objects_done->push_back(ob); - if (parent_node == NULL) { - root_objects->push_back(ob); - } - } - ++camera_done; - } - while (lamp_done < lamp.getCount()) { - ob = create_light_object(lamp[lamp_done], sce); - if (ob == NULL) { - report_unknown_reference(*node, "instance_light"); - } - else { - objects_done->push_back(ob); - if (parent_node == NULL) { - root_objects->push_back(ob); - } - } - ++lamp_done; - } - while (controller_done < controller.getCount()) { - COLLADAFW::InstanceGeometry *geometry = (COLLADAFW::InstanceGeometry *)controller[controller_done]; - ob = mesh_importer.create_mesh_object(node, geometry, true, uid_material_map); - if (ob == NULL) { - report_unknown_reference(*node, "instance_controller"); - } - else { - objects_done->push_back(ob); - if (parent_node == NULL) { - root_objects->push_back(ob); - } - } - ++controller_done; - } - // XXX instance_node is not supported yet - while (inst_done < inst_node.getCount()) { - const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId(); - if (object_map.find(node_id) == object_map.end()) { - fprintf(stderr, "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", inst_node[inst_done]->getName().c_str()); - ob = NULL; - } - else { - std::pair<std::multimap<COLLADAFW::UniqueId, Object *>::iterator, std::multimap<COLLADAFW::UniqueId, Object *>::iterator> pair_iter = object_map.equal_range(node_id); - for (std::multimap<COLLADAFW::UniqueId, Object *>::iterator it2 = pair_iter.first; it2 != pair_iter.second; it2++) { - Object *source_ob = (Object *)it2->second; - COLLADAFW::Node *source_node = node_map[node_id]; - ob = create_instance_node(source_ob, source_node, node, sce, is_library_node); - objects_done->push_back(ob); - if (parent_node == NULL) { - root_objects->push_back(ob); - } - } - } - ++inst_done; - - read_transform = false; - } - - // if node is empty - create empty object - // XXX empty node may not mean it is empty object, not sure about this - if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { - //Check if Object is armature, by checking if immediate child is a JOINT node. - if (is_armature(node)) { - ob = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, name.c_str()); - } - else { - ob = bc_add_object(bmain, sce, view_layer, OB_EMPTY, NULL); - } - objects_done->push_back(ob); - if (parent_node == NULL) { - root_objects->push_back(ob); - } - } - - // XXX: if there're multiple instances, only one is stored - - if (!ob) { - goto finally; - } - - for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { - ob = *it; - std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); - BKE_libblock_rename(bmain, &ob->id, (char *)nodename.c_str()); - object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob)); - node_map[node->getUniqueId()] = node; - - if (is_library_node) - libnode_ob.push_back(ob); - } - - - //create_constraints(et,ob); - - } - - for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { - ob = *it; - - if (read_transform) - anim_importer.read_node_transform(node, ob); // overwrites location set earlier - - if (!is_joint) { - if (par && ob) { - ob->parent = par; - ob->partype = PAROBJECT; - ob->parsubstr[0] = 0; - - //bc_set_parent(ob, par, mContext, false); - } - } - } - - if (objects_done->size() > 0) { - ob = *objects_done->begin(); - } - else { - ob = NULL; - } - - for (unsigned int i = 0; i < child_nodes.getCount(); i++) { - std::vector<Object *> *child_objects; - child_objects = write_node(child_nodes[i], node, sce, ob, is_library_node); - delete child_objects; - } - + Main *bmain = CTX_data_main(mContext); + Object *ob = NULL; + bool is_joint = node->getType() == COLLADAFW::Node::JOINT; + bool read_transform = true; + std::string id = node->getOriginalId(); + std::string name = node->getName(); + + // if node has child nodes write them + COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); + + std::vector<Object *> *objects_done = new std::vector<Object *>(); + std::vector<Object *> *root_objects = new std::vector<Object *>(); + + fprintf( + stderr, "| %s id='%s', name='%s'\n", is_joint ? "JOINT" : "NODE ", id.c_str(), name.c_str()); + + if (is_joint) { + if (parent_node == NULL && !is_library_node) { + // A Joint on root level is a skeleton without root node. + // Here we add the armature "on the fly": + par = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, std::string("Armature").c_str()); + objects_done->push_back(par); + root_objects->push_back(par); + object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par)); + node_map[node->getUniqueId()] = node; + } + if (parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT) { + armature_importer.add_root_joint(node, par); + } + + if (parent_node == NULL) { + // for skeletons without root node all has been done above. + // Skeletons with root node are handled further down. + goto finally; + } + } + else { + COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries(); + COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras(); + COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights(); + COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers(); + COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes(); + size_t geom_done = 0; + size_t camera_done = 0; + size_t lamp_done = 0; + size_t controller_done = 0; + size_t inst_done = 0; + + // XXX linking object with the first <instance_geometry>, though a node may have more of them... + // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure... + // <instance_geometry> + while (geom_done < geom.getCount()) { + ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map); + if (ob == NULL) { + report_unknown_reference(*node, "instance_mesh"); + } + else { + objects_done->push_back(ob); + if (parent_node == NULL) { + root_objects->push_back(ob); + } + } + ++geom_done; + } + while (camera_done < camera.getCount()) { + ob = create_camera_object(camera[camera_done], sce); + if (ob == NULL) { + report_unknown_reference(*node, "instance_camera"); + } + else { + objects_done->push_back(ob); + if (parent_node == NULL) { + root_objects->push_back(ob); + } + } + ++camera_done; + } + while (lamp_done < lamp.getCount()) { + ob = create_light_object(lamp[lamp_done], sce); + if (ob == NULL) { + report_unknown_reference(*node, "instance_light"); + } + else { + objects_done->push_back(ob); + if (parent_node == NULL) { + root_objects->push_back(ob); + } + } + ++lamp_done; + } + while (controller_done < controller.getCount()) { + COLLADAFW::InstanceGeometry *geometry = (COLLADAFW::InstanceGeometry *) + controller[controller_done]; + ob = mesh_importer.create_mesh_object(node, geometry, true, uid_material_map); + if (ob == NULL) { + report_unknown_reference(*node, "instance_controller"); + } + else { + objects_done->push_back(ob); + if (parent_node == NULL) { + root_objects->push_back(ob); + } + } + ++controller_done; + } + // XXX instance_node is not supported yet + while (inst_done < inst_node.getCount()) { + const COLLADAFW::UniqueId &node_id = inst_node[inst_done]->getInstanciatedObjectId(); + if (object_map.find(node_id) == object_map.end()) { + fprintf(stderr, + "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", + inst_node[inst_done]->getName().c_str()); + ob = NULL; + } + else { + std::pair<std::multimap<COLLADAFW::UniqueId, Object *>::iterator, + std::multimap<COLLADAFW::UniqueId, Object *>::iterator> + pair_iter = object_map.equal_range(node_id); + for (std::multimap<COLLADAFW::UniqueId, Object *>::iterator it2 = pair_iter.first; + it2 != pair_iter.second; + it2++) { + Object *source_ob = (Object *)it2->second; + COLLADAFW::Node *source_node = node_map[node_id]; + ob = create_instance_node(source_ob, source_node, node, sce, is_library_node); + objects_done->push_back(ob); + if (parent_node == NULL) { + root_objects->push_back(ob); + } + } + } + ++inst_done; + + read_transform = false; + } + + // if node is empty - create empty object + // XXX empty node may not mean it is empty object, not sure about this + if ((geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { + //Check if Object is armature, by checking if immediate child is a JOINT node. + if (is_armature(node)) { + ob = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, name.c_str()); + } + else { + ob = bc_add_object(bmain, sce, view_layer, OB_EMPTY, NULL); + } + objects_done->push_back(ob); + if (parent_node == NULL) { + root_objects->push_back(ob); + } + } + + // XXX: if there're multiple instances, only one is stored + + if (!ob) { + goto finally; + } + + for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); + ++it) { + ob = *it; + std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); + BKE_libblock_rename(bmain, &ob->id, (char *)nodename.c_str()); + object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob)); + node_map[node->getUniqueId()] = node; + + if (is_library_node) + libnode_ob.push_back(ob); + } + + //create_constraints(et,ob); + } + + for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); + ++it) { + ob = *it; + + if (read_transform) + anim_importer.read_node_transform(node, ob); // overwrites location set earlier + + if (!is_joint) { + if (par && ob) { + ob->parent = par; + ob->partype = PAROBJECT; + ob->parsubstr[0] = 0; + + //bc_set_parent(ob, par, mContext, false); + } + } + } + + if (objects_done->size() > 0) { + ob = *objects_done->begin(); + } + else { + ob = NULL; + } + + for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + std::vector<Object *> *child_objects; + child_objects = write_node(child_nodes[i], node, sce, ob, is_library_node); + delete child_objects; + } finally: - delete objects_done; + delete objects_done; - return root_objects; + return root_objects; } /** @@ -694,22 +712,22 @@ finally: */ bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - // this method called on post process after writeGeometry, writeMaterial, etc. + // this method called on post process after writeGeometry, writeMaterial, etc. - // for each <node> in <visual_scene>: - // create an Object - // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh + // for each <node> in <visual_scene>: + // create an Object + // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh - // update: since we cannot link a Mesh with Object in - // writeGeometry because <geometry> does not reference <node>, - // we link Objects with Meshes here + // update: since we cannot link a Mesh with Object in + // writeGeometry because <geometry> does not reference <node>, + // we link Objects with Meshes here - vscenes.push_back(visualScene); + vscenes.push_back(visualScene); - return true; + return true; } /** When this method is called, the writer must handle all nodes contained in the @@ -717,61 +735,60 @@ bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScen * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - Scene *sce = CTX_data_scene(mContext); + Scene *sce = CTX_data_scene(mContext); - const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes(); + const COLLADAFW::NodePointerArray &nodes = libraryNodes->getNodes(); - fprintf(stderr, "+-- Read Library nodes ----------\n"); - for (unsigned int i = 0; i < nodes.getCount(); i++) { - std::vector<Object *> *child_objects; - child_objects = write_node(nodes[i], NULL, sce, NULL, true); - delete child_objects; - } - return true; + fprintf(stderr, "+-- Read Library nodes ----------\n"); + for (unsigned int i = 0; i < nodes.getCount(); i++) { + std::vector<Object *> *child_objects; + child_objects = write_node(nodes[i], NULL, sce, NULL, true); + delete child_objects; + } + return true; } /** When this method is called, the writer must write the geometry. * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - return mesh_importer.write_geometry(geom); + return mesh_importer.write_geometry(geom); } /** When this method is called, the writer must write the material. * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - Main *bmain = CTX_data_main(mContext); - const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId(); - Material *ma = BKE_material_add(bmain, (char *)str_mat_id.c_str()); + Main *bmain = CTX_data_main(mContext); + const std::string &str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId(); + Material *ma = BKE_material_add(bmain, (char *)str_mat_id.c_str()); - this->uid_effect_map[cmat->getInstantiatedEffect()] = ma; - this->uid_material_map[cmat->getUniqueId()] = ma; + this->uid_effect_map[cmat->getInstantiatedEffect()] = ma; + this->uid_material_map[cmat->getUniqueId()] = ma; - return true; + return true; } - void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma) { - MaterialNode matNode = MaterialNode(mContext, ef, ma, uid_image_map); - matNode.set_reflectivity(ef->getReflectivity().getFloatValue()); - matNode.set_ior(ef->getIndexOfRefraction().getFloatValue()); - matNode.set_diffuse(ef->getDiffuse(), "Diffuse"); - matNode.set_ambient(ef->getAmbient(), "Ambient"); - matNode.set_specular(ef->getSpecular(), "Specular"); - matNode.set_reflective(ef->getReflective(), "Reflective"); - matNode.set_emission(ef->getEmission(), "Emission"); - matNode.set_opacity(ef->getOpacity(), "Opacity"); + MaterialNode matNode = MaterialNode(mContext, ef, ma, uid_image_map); + matNode.set_reflectivity(ef->getReflectivity().getFloatValue()); + matNode.set_ior(ef->getIndexOfRefraction().getFloatValue()); + matNode.set_diffuse(ef->getDiffuse(), "Diffuse"); + matNode.set_ambient(ef->getAmbient(), "Ambient"); + matNode.set_specular(ef->getSpecular(), "Specular"); + matNode.set_reflective(ef->getReflective(), "Reflective"); + matNode.set_emission(ef->getEmission(), "Emission"); + matNode.set_opacity(ef->getOpacity(), "Opacity"); } /** When this method is called, the writer must write the effect. @@ -779,367 +796,340 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect) { - if (mImportStage == Fetching_Controller_data) - return true; - - const COLLADAFW::UniqueId& uid = effect->getUniqueId(); - - if (uid_effect_map.find(uid) == uid_effect_map.end()) { - fprintf(stderr, "Couldn't find a material by UID.\n"); - return true; - } - - Material *ma = uid_effect_map[uid]; - std::map<COLLADAFW::UniqueId, Material *>::iterator iter; - for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) { - if (iter->second == ma) { - this->FW_object_map[iter->first] = effect; - break; - } - } - COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects(); - if (common_efs.getCount() < 1) { - fprintf(stderr, "Couldn't find <profile_COMMON>.\n"); - return true; - } - // XXX TODO: Take all <profile_common>s - // Currently only first <profile_common> is supported - COLLADAFW::EffectCommon *ef = common_efs[0]; - write_profile_COMMON(ef, ma); - this->FW_object_map[effect->getUniqueId()] = effect; - - return true; + if (mImportStage == Fetching_Controller_data) + return true; + + const COLLADAFW::UniqueId &uid = effect->getUniqueId(); + + if (uid_effect_map.find(uid) == uid_effect_map.end()) { + fprintf(stderr, "Couldn't find a material by UID.\n"); + return true; + } + + Material *ma = uid_effect_map[uid]; + std::map<COLLADAFW::UniqueId, Material *>::iterator iter; + for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) { + if (iter->second == ma) { + this->FW_object_map[iter->first] = effect; + break; + } + } + COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects(); + if (common_efs.getCount() < 1) { + fprintf(stderr, "Couldn't find <profile_COMMON>.\n"); + return true; + } + // XXX TODO: Take all <profile_common>s + // Currently only first <profile_common> is supported + COLLADAFW::EffectCommon *ef = common_efs[0]; + write_profile_COMMON(ef, ma); + this->FW_object_map[effect->getUniqueId()] = effect; + + return true; } - /** When this method is called, the writer must write the camera. * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) { - if (mImportStage == Fetching_Controller_data) - return true; - - Main *bmain = CTX_data_main(mContext); - Camera *cam = NULL; - std::string cam_id, cam_name; - - ExtraTags *et=getExtraTags(camera->getUniqueId()); - cam_id = camera->getOriginalId(); - cam_name = camera->getName(); - if (cam_name.size()) cam = (Camera *)BKE_camera_add(bmain, (char *)cam_name.c_str()); - else cam = (Camera *)BKE_camera_add(bmain, (char *)cam_id.c_str()); - - if (!cam) { - fprintf(stderr, "Cannot create camera.\n"); - return true; - } - - if (et && et->isProfile("blender")) { - et->setData("shiftx",&(cam->shiftx)); - et->setData("shifty",&(cam->shifty)); - et->setData("dof_distance",&(cam->dof_distance)); - } - cam->clip_start = camera->getNearClippingPlane().getValue(); - cam->clip_end = camera->getFarClippingPlane().getValue(); - - COLLADAFW::Camera::CameraType type = camera->getCameraType(); - switch (type) { - case COLLADAFW::Camera::ORTHOGRAPHIC: - { - cam->type = CAM_ORTHO; - } - break; - case COLLADAFW::Camera::PERSPECTIVE: - { - cam->type = CAM_PERSP; - } - break; - case COLLADAFW::Camera::UNDEFINED_CAMERATYPE: - { - fprintf(stderr, "Current camera type is not supported.\n"); - cam->type = CAM_PERSP; - } - break; - } - - switch (camera->getDescriptionType()) { - case COLLADAFW::Camera::ASPECTRATIO_AND_Y: - { - switch (cam->type) { - case CAM_ORTHO: - { - double ymag = 2 * camera->getYMag().getValue(); - double aspect = camera->getAspectRatio().getValue(); - double xmag = aspect * ymag; - cam->ortho_scale = (float)xmag; - } - break; - case CAM_PERSP: - default: - { - double yfov = camera->getYFov().getValue(); - double aspect = camera->getAspectRatio().getValue(); - - // NOTE: Needs more testing (As we curretnly have no official test data for this) - - double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f)); - cam->lens = fov_to_focallength(xfov, cam->sensor_x); - } - break; - } - } - break; - /* XXX correct way to do following four is probably to get also render - * size and determine proper settings from that somehow */ - case COLLADAFW::Camera::ASPECTRATIO_AND_X: - case COLLADAFW::Camera::SINGLE_X: - case COLLADAFW::Camera::X_AND_Y: - { - switch (cam->type) { - case CAM_ORTHO: - cam->ortho_scale = (float)camera->getXMag().getValue() * 2; - break; - case CAM_PERSP: - default: - { - double x = camera->getXFov().getValue(); - // x is in degrees, cam->lens is in millimiters - cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x); - } - break; - } - } - break; - case COLLADAFW::Camera::SINGLE_Y: - { - switch (cam->type) { - case CAM_ORTHO: - cam->ortho_scale = (float)camera->getYMag().getValue(); - break; - case CAM_PERSP: - default: - { - double yfov = camera->getYFov().getValue(); - // yfov is in degrees, cam->lens is in millimiters - cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x); - } - break; - } - } - break; - case COLLADAFW::Camera::UNDEFINED: - // read nothing, use blender defaults. - break; - } - - this->uid_camera_map[camera->getUniqueId()] = cam; - this->FW_object_map[camera->getUniqueId()] = camera; - // XXX import camera options - return true; + if (mImportStage == Fetching_Controller_data) + return true; + + Main *bmain = CTX_data_main(mContext); + Camera *cam = NULL; + std::string cam_id, cam_name; + + ExtraTags *et = getExtraTags(camera->getUniqueId()); + cam_id = camera->getOriginalId(); + cam_name = camera->getName(); + if (cam_name.size()) + cam = (Camera *)BKE_camera_add(bmain, (char *)cam_name.c_str()); + else + cam = (Camera *)BKE_camera_add(bmain, (char *)cam_id.c_str()); + + if (!cam) { + fprintf(stderr, "Cannot create camera.\n"); + return true; + } + + if (et && et->isProfile("blender")) { + et->setData("shiftx", &(cam->shiftx)); + et->setData("shifty", &(cam->shifty)); + et->setData("dof_distance", &(cam->dof_distance)); + } + cam->clip_start = camera->getNearClippingPlane().getValue(); + cam->clip_end = camera->getFarClippingPlane().getValue(); + + COLLADAFW::Camera::CameraType type = camera->getCameraType(); + switch (type) { + case COLLADAFW::Camera::ORTHOGRAPHIC: { + cam->type = CAM_ORTHO; + } break; + case COLLADAFW::Camera::PERSPECTIVE: { + cam->type = CAM_PERSP; + } break; + case COLLADAFW::Camera::UNDEFINED_CAMERATYPE: { + fprintf(stderr, "Current camera type is not supported.\n"); + cam->type = CAM_PERSP; + } break; + } + + switch (camera->getDescriptionType()) { + case COLLADAFW::Camera::ASPECTRATIO_AND_Y: { + switch (cam->type) { + case CAM_ORTHO: { + double ymag = 2 * camera->getYMag().getValue(); + double aspect = camera->getAspectRatio().getValue(); + double xmag = aspect * ymag; + cam->ortho_scale = (float)xmag; + } break; + case CAM_PERSP: + default: { + double yfov = camera->getYFov().getValue(); + double aspect = camera->getAspectRatio().getValue(); + + // NOTE: Needs more testing (As we curretnly have no official test data for this) + + double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f)); + cam->lens = fov_to_focallength(xfov, cam->sensor_x); + } break; + } + } break; + /* XXX correct way to do following four is probably to get also render + * size and determine proper settings from that somehow */ + case COLLADAFW::Camera::ASPECTRATIO_AND_X: + case COLLADAFW::Camera::SINGLE_X: + case COLLADAFW::Camera::X_AND_Y: { + switch (cam->type) { + case CAM_ORTHO: + cam->ortho_scale = (float)camera->getXMag().getValue() * 2; + break; + case CAM_PERSP: + default: { + double x = camera->getXFov().getValue(); + // x is in degrees, cam->lens is in millimiters + cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x); + } break; + } + } break; + case COLLADAFW::Camera::SINGLE_Y: { + switch (cam->type) { + case CAM_ORTHO: + cam->ortho_scale = (float)camera->getYMag().getValue(); + break; + case CAM_PERSP: + default: { + double yfov = camera->getYFov().getValue(); + // yfov is in degrees, cam->lens is in millimiters + cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x); + } break; + } + } break; + case COLLADAFW::Camera::UNDEFINED: + // read nothing, use blender defaults. + break; + } + + this->uid_camera_map[camera->getUniqueId()] = cam; + this->FW_object_map[camera->getUniqueId()] = camera; + // XXX import camera options + return true; } /** When this method is called, the writer must write the image. * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeImage(const COLLADAFW::Image *image) { - if (mImportStage == Fetching_Controller_data) - return true; - - const std::string& imagepath = image->getImageURI().toNativePath(); - - char dir[FILE_MAX]; - char absolute_path[FILE_MAX]; - const char *workpath; - - BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir)); - BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str()); - if (BLI_exists(absolute_path)) { - workpath = absolute_path; - } - else { - // Maybe imagepath was already absolute ? - if (!BLI_exists(imagepath.c_str())) { - fprintf(stderr, "|! Image not found: %s\n", imagepath.c_str() ); - return true; - } - workpath = imagepath.c_str(); - } - - Image *ima = BKE_image_load_exists(CTX_data_main(mContext), workpath); - if (!ima) { - fprintf(stderr, "|! Cannot create image: %s\n", workpath); - return true; - } - this->uid_image_map[image->getUniqueId()] = ima; - fprintf(stderr, "| import Image: %s\n", workpath); - return true; + if (mImportStage == Fetching_Controller_data) + return true; + + const std::string &imagepath = image->getImageURI().toNativePath(); + + char dir[FILE_MAX]; + char absolute_path[FILE_MAX]; + const char *workpath; + + BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir)); + BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str()); + if (BLI_exists(absolute_path)) { + workpath = absolute_path; + } + else { + // Maybe imagepath was already absolute ? + if (!BLI_exists(imagepath.c_str())) { + fprintf(stderr, "|! Image not found: %s\n", imagepath.c_str()); + return true; + } + workpath = imagepath.c_str(); + } + + Image *ima = BKE_image_load_exists(CTX_data_main(mContext), workpath); + if (!ima) { + fprintf(stderr, "|! Cannot create image: %s\n", workpath); + return true; + } + this->uid_image_map[image->getUniqueId()] = ima; + fprintf(stderr, "| import Image: %s\n", workpath); + return true; } /** When this method is called, the writer must write the light. * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeLight(const COLLADAFW::Light *light) { - if (mImportStage == Fetching_Controller_data) - return true; - - Main *bmain = CTX_data_main(mContext); - Light *lamp = NULL; - std::string la_id, la_name; - - ExtraTags *et = getExtraTags(light->getUniqueId()); - /*TagsMap::iterator etit; - ExtraTags *et = 0; - etit = uid_tags_map.find(light->getUniqueId().toAscii()); - if (etit != uid_tags_map.end()) - et = etit->second;*/ - - la_id = light->getOriginalId(); - la_name = light->getName(); - if (la_name.size()) lamp = (Light *)BKE_light_add(bmain, (char *)la_name.c_str()); - else lamp = (Light *)BKE_light_add(bmain, (char *)la_id.c_str()); - - if (!lamp) { - fprintf(stderr, "Cannot create light.\n"); - return true; - } - - // if we find an ExtraTags for this, use that instead. - if (et && et->isProfile("blender")) { - et->setData("type", &(lamp->type)); - et->setData("flag", &(lamp->flag)); - et->setData("mode", &(lamp->mode)); - et->setData("gamma", &(lamp->k)); - et->setData("red", &(lamp->r)); - et->setData("green", &(lamp->g)); - et->setData("blue", &(lamp->b)); - et->setData("shadow_r", &(lamp->shdwr)); - et->setData("shadow_g", &(lamp->shdwg)); - et->setData("shadow_b", &(lamp->shdwb)); - et->setData("energy", &(lamp->energy)); - et->setData("dist", &(lamp->dist)); - et->setData("spotsize", &(lamp->spotsize)); - lamp->spotsize = DEG2RADF(lamp->spotsize); - et->setData("spotblend", &(lamp->spotblend)); - et->setData("att1", &(lamp->att1)); - et->setData("att2", &(lamp->att2)); - et->setData("falloff_type", &(lamp->falloff_type)); - et->setData("clipsta", &(lamp->clipsta)); - et->setData("clipend", &(lamp->clipend)); - et->setData("bias", &(lamp->bias)); - et->setData("soft", &(lamp->soft)); - et->setData("bufsize", &(lamp->bufsize)); - et->setData("buffers", &(lamp->buffers)); - et->setData("area_shape", &(lamp->area_shape)); - et->setData("area_size", &(lamp->area_size)); - et->setData("area_sizey", &(lamp->area_sizey)); - et->setData("area_sizez", &(lamp->area_sizez)); - } - else { - float constatt = light->getConstantAttenuation().getValue(); - float linatt = light->getLinearAttenuation().getValue(); - float quadatt = light->getQuadraticAttenuation().getValue(); - float d = 25.0f; - float att1 = 0.0f; - float att2 = 0.0f; - float e = 1.0f; - - if (light->getColor().isValid()) { - COLLADAFW::Color col = light->getColor(); - lamp->r = col.getRed(); - lamp->g = col.getGreen(); - lamp->b = col.getBlue(); - } - - if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) { - att2 = quadatt; - d = sqrt(1.0f / quadatt); - } - // linear light - else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) { - att1 = linatt; - d = (1.0f / linatt); - } - else if (IS_EQ(constatt, 1.0f)) { - att1 = 1.0f; - } - else { - // assuming point light (const att = 1.0); - att1 = 1.0f; - } - - d *= (1.0f / unit_converter.getLinearMeter()); - - lamp->energy = e; - lamp->dist = d; - - switch (light->getLightType()) { - case COLLADAFW::Light::AMBIENT_LIGHT: - { - lamp->type = LA_SUN; //TODO needs more thoughts - } - break; - case COLLADAFW::Light::SPOT_LIGHT: - { - lamp->type = LA_SPOT; - lamp->att1 = att1; - lamp->att2 = att2; - if (IS_EQ(att1, 0.0f) && att2 > 0) - lamp->falloff_type = LA_FALLOFF_INVSQUARE; - if (IS_EQ(att2, 0.0f) && att1 > 0) - lamp->falloff_type = LA_FALLOFF_INVLINEAR; - lamp->spotsize = DEG2RADF(light->getFallOffAngle().getValue()); - lamp->spotblend = light->getFallOffExponent().getValue(); - } - break; - case COLLADAFW::Light::DIRECTIONAL_LIGHT: - { - /* our sun is very strong, so pick a smaller energy level */ - lamp->type = LA_SUN; - } - break; - case COLLADAFW::Light::POINT_LIGHT: - { - lamp->type = LA_LOCAL; - lamp->att1 = att1; - lamp->att2 = att2; - if (IS_EQ(att1, 0.0f) && att2 > 0) - lamp->falloff_type = LA_FALLOFF_INVSQUARE; - if (IS_EQ(att2, 0.0f) && att1 > 0) - lamp->falloff_type = LA_FALLOFF_INVLINEAR; - } - break; - case COLLADAFW::Light::UNDEFINED: - { - fprintf(stderr, "Current light type is not supported.\n"); - lamp->type = LA_LOCAL; - } - break; - } - } - - this->uid_light_map[light->getUniqueId()] = lamp; - this->FW_object_map[light->getUniqueId()] = light; - return true; + if (mImportStage == Fetching_Controller_data) + return true; + + Main *bmain = CTX_data_main(mContext); + Light *lamp = NULL; + std::string la_id, la_name; + + ExtraTags *et = getExtraTags(light->getUniqueId()); + /*TagsMap::iterator etit; + ExtraTags *et = 0; + etit = uid_tags_map.find(light->getUniqueId().toAscii()); + if (etit != uid_tags_map.end()) + et = etit->second;*/ + + la_id = light->getOriginalId(); + la_name = light->getName(); + if (la_name.size()) + lamp = (Light *)BKE_light_add(bmain, (char *)la_name.c_str()); + else + lamp = (Light *)BKE_light_add(bmain, (char *)la_id.c_str()); + + if (!lamp) { + fprintf(stderr, "Cannot create light.\n"); + return true; + } + + // if we find an ExtraTags for this, use that instead. + if (et && et->isProfile("blender")) { + et->setData("type", &(lamp->type)); + et->setData("flag", &(lamp->flag)); + et->setData("mode", &(lamp->mode)); + et->setData("gamma", &(lamp->k)); + et->setData("red", &(lamp->r)); + et->setData("green", &(lamp->g)); + et->setData("blue", &(lamp->b)); + et->setData("shadow_r", &(lamp->shdwr)); + et->setData("shadow_g", &(lamp->shdwg)); + et->setData("shadow_b", &(lamp->shdwb)); + et->setData("energy", &(lamp->energy)); + et->setData("dist", &(lamp->dist)); + et->setData("spotsize", &(lamp->spotsize)); + lamp->spotsize = DEG2RADF(lamp->spotsize); + et->setData("spotblend", &(lamp->spotblend)); + et->setData("att1", &(lamp->att1)); + et->setData("att2", &(lamp->att2)); + et->setData("falloff_type", &(lamp->falloff_type)); + et->setData("clipsta", &(lamp->clipsta)); + et->setData("clipend", &(lamp->clipend)); + et->setData("bias", &(lamp->bias)); + et->setData("soft", &(lamp->soft)); + et->setData("bufsize", &(lamp->bufsize)); + et->setData("buffers", &(lamp->buffers)); + et->setData("area_shape", &(lamp->area_shape)); + et->setData("area_size", &(lamp->area_size)); + et->setData("area_sizey", &(lamp->area_sizey)); + et->setData("area_sizez", &(lamp->area_sizez)); + } + else { + float constatt = light->getConstantAttenuation().getValue(); + float linatt = light->getLinearAttenuation().getValue(); + float quadatt = light->getQuadraticAttenuation().getValue(); + float d = 25.0f; + float att1 = 0.0f; + float att2 = 0.0f; + float e = 1.0f; + + if (light->getColor().isValid()) { + COLLADAFW::Color col = light->getColor(); + lamp->r = col.getRed(); + lamp->g = col.getGreen(); + lamp->b = col.getBlue(); + } + + if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) { + att2 = quadatt; + d = sqrt(1.0f / quadatt); + } + // linear light + else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) { + att1 = linatt; + d = (1.0f / linatt); + } + else if (IS_EQ(constatt, 1.0f)) { + att1 = 1.0f; + } + else { + // assuming point light (const att = 1.0); + att1 = 1.0f; + } + + d *= (1.0f / unit_converter.getLinearMeter()); + + lamp->energy = e; + lamp->dist = d; + + switch (light->getLightType()) { + case COLLADAFW::Light::AMBIENT_LIGHT: { + lamp->type = LA_SUN; //TODO needs more thoughts + } break; + case COLLADAFW::Light::SPOT_LIGHT: { + lamp->type = LA_SPOT; + lamp->att1 = att1; + lamp->att2 = att2; + if (IS_EQ(att1, 0.0f) && att2 > 0) + lamp->falloff_type = LA_FALLOFF_INVSQUARE; + if (IS_EQ(att2, 0.0f) && att1 > 0) + lamp->falloff_type = LA_FALLOFF_INVLINEAR; + lamp->spotsize = DEG2RADF(light->getFallOffAngle().getValue()); + lamp->spotblend = light->getFallOffExponent().getValue(); + } break; + case COLLADAFW::Light::DIRECTIONAL_LIGHT: { + /* our sun is very strong, so pick a smaller energy level */ + lamp->type = LA_SUN; + } break; + case COLLADAFW::Light::POINT_LIGHT: { + lamp->type = LA_LOCAL; + lamp->att1 = att1; + lamp->att2 = att2; + if (IS_EQ(att1, 0.0f) && att2 > 0) + lamp->falloff_type = LA_FALLOFF_INVSQUARE; + if (IS_EQ(att2, 0.0f) && att1 > 0) + lamp->falloff_type = LA_FALLOFF_INVLINEAR; + } break; + case COLLADAFW::Light::UNDEFINED: { + fprintf(stderr, "Current light type is not supported.\n"); + lamp->type = LA_LOCAL; + } break; + } + } + + this->uid_light_map[light->getUniqueId()] = lamp; + this->FW_object_map[light->getUniqueId()] = light; + return true; } // this function is called only for animations that pass COLLADAFW::validate bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - // return true; - return anim_importer.write_animation(anim); + // return true; + return anim_importer.write_animation(anim); } // called on post-process stage after writeVisualScenes bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - // return true; - return anim_importer.write_animation_list(animationList); + // return true; + return anim_importer.write_animation_list(animationList); } #if WITH_OPENCOLLADA_ANIMATION_CLIP @@ -1147,11 +1137,11 @@ bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animat // called on post-process stage after writeVisualScenes bool DocumentImporter::writeAnimationClip(const COLLADAFW::AnimationClip *animationClip) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - return true; - //return animation_clip_importer.write_animation_clip(animationClip); // TODO: implement import of AnimationClips + return true; + //return animation_clip_importer.write_animation_clip(animationClip); // TODO: implement import of AnimationClips } #endif @@ -1159,54 +1149,54 @@ bool DocumentImporter::writeAnimationClip(const COLLADAFW::AnimationClip *animat * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin) { - return armature_importer.write_skin_controller_data(skin); + return armature_importer.write_skin_controller_data(skin); } // this is called on postprocess, before writeVisualScenes bool DocumentImporter::writeController(const COLLADAFW::Controller *controller) { - if (mImportStage == Fetching_Controller_data) - return true; + if (mImportStage == Fetching_Controller_data) + return true; - return armature_importer.write_controller(controller); + return armature_importer.write_controller(controller); } bool DocumentImporter::writeFormulas(const COLLADAFW::Formulas *formulas) { - return true; + return true; } bool DocumentImporter::writeKinematicsScene(const COLLADAFW::KinematicsScene *kinematicsScene) { - return true; + return true; } ExtraTags *DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid) { - if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) { - return NULL; - } - return uid_tags_map[uid.toAscii()]; + if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) { + return NULL; + } + return uid_tags_map[uid.toAscii()]; } bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags) { - uid_tags_map[uid.toAscii()] = extra_tags; - return true; + uid_tags_map[uid.toAscii()] = extra_tags; + return true; } bool DocumentImporter::is_armature(COLLADAFW::Node *node) { - COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); - for (unsigned int i = 0; i < child_nodes.getCount(); i++) { - if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) { - return true; - } - else { - continue; - } - } - - //no child is JOINT - return false; + COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); + for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) { + return true; + } + else { + continue; + } + } + + //no child is JOINT + return false; } diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index 1ba1a9c5388..b48ddaaa827 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -32,7 +32,6 @@ #include "COLLADAFWSkinController.h" #include "COLLADAFWEffectCommon.h" - #include "BKE_object.h" #include "BKE_constraint.h" @@ -46,130 +45,127 @@ struct bContext; /** Importer class. */ -class DocumentImporter : COLLADAFW::IWriter -{ -public: - //! Enumeration to denote the stage of import - enum ImportStage { - Fetching_Scene_data, /* First pass to collect all data except controller */ - Fetching_Controller_data, /* Second pass to collect controller data */ - }; - /** Constructor */ - DocumentImporter(bContext *C, const ImportSettings *import_settings); +class DocumentImporter : COLLADAFW::IWriter { + public: + //! Enumeration to denote the stage of import + enum ImportStage { + Fetching_Scene_data, /* First pass to collect all data except controller */ + Fetching_Controller_data, /* Second pass to collect controller data */ + }; + /** Constructor */ + DocumentImporter(bContext *C, const ImportSettings *import_settings); - /** Destructor */ - ~DocumentImporter(); + /** Destructor */ + ~DocumentImporter(); - /** Function called by blender UI */ - bool import(); + /** Function called by blender UI */ + bool import(); - /** these should not be here */ - Object* create_camera_object(COLLADAFW::InstanceCamera*, Scene*); - Object* create_light_object(COLLADAFW::InstanceLight*, Scene*); - Object* create_instance_node(Object*, COLLADAFW::Node*, COLLADAFW::Node*, Scene*, bool); - void create_constraints(ExtraTags *et, Object *ob); - std::vector<Object *> *write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool); - void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*); + /** these should not be here */ + Object *create_camera_object(COLLADAFW::InstanceCamera *, Scene *); + Object *create_light_object(COLLADAFW::InstanceLight *, Scene *); + Object *create_instance_node(Object *, COLLADAFW::Node *, COLLADAFW::Node *, Scene *, bool); + void create_constraints(ExtraTags *et, Object *ob); + std::vector<Object *> *write_node(COLLADAFW::Node *, COLLADAFW::Node *, Scene *, Object *, bool); + void write_profile_COMMON(COLLADAFW::EffectCommon *, Material *); - void translate_anim_recursive(COLLADAFW::Node*, COLLADAFW::Node*, Object*); + void translate_anim_recursive(COLLADAFW::Node *, COLLADAFW::Node *, Object *); - /** - * This method will be called if an error in the loading process occurred and the loader cannot - * continue to load. The writer should undo all operations that have been performed. - * \param errorMessage: A message containing information about the error that occurred. - */ - void cancel(const COLLADAFW::String& errorMessage); + /** + * This method will be called if an error in the loading process occurred and the loader cannot + * continue to load. The writer should undo all operations that have been performed. + * \param errorMessage: A message containing information about the error that occurred. + */ + void cancel(const COLLADAFW::String &errorMessage); - /** This is the method called. The writer hast to prepare to receive data.*/ - void start(); + /** This is the method called. The writer hast to prepare to receive data.*/ + void start(); - /** This method is called after the last write* method. No other methods will be called after this.*/ - void finish(); + /** This method is called after the last write* method. No other methods will be called after this.*/ + void finish(); - bool writeGlobalAsset(const COLLADAFW::FileInfo*); - std::string get_import_version(const COLLADAFW::FileInfo *asset); + bool writeGlobalAsset(const COLLADAFW::FileInfo *); + std::string get_import_version(const COLLADAFW::FileInfo *asset); - bool writeScene(const COLLADAFW::Scene*); + bool writeScene(const COLLADAFW::Scene *); - bool writeVisualScene(const COLLADAFW::VisualScene*); + bool writeVisualScene(const COLLADAFW::VisualScene *); - bool writeLibraryNodes(const COLLADAFW::LibraryNodes*); + bool writeLibraryNodes(const COLLADAFW::LibraryNodes *); - bool writeAnimation(const COLLADAFW::Animation*); + bool writeAnimation(const COLLADAFW::Animation *); - bool writeAnimationList(const COLLADAFW::AnimationList*); + bool writeAnimationList(const COLLADAFW::AnimationList *); #if WITH_OPENCOLLADA_ANIMATION_CLIP - // Please enable this when building with Collada 1.6.65 or newer (also in DocumentImporter.cpp) - bool writeAnimationClip(const COLLADAFW::AnimationClip *animationClip); + // Please enable this when building with Collada 1.6.65 or newer (also in DocumentImporter.cpp) + bool writeAnimationClip(const COLLADAFW::AnimationClip *animationClip); #endif - bool writeGeometry(const COLLADAFW::Geometry*); - - bool writeMaterial(const COLLADAFW::Material*); - - bool writeEffect(const COLLADAFW::Effect*); - - bool writeCamera(const COLLADAFW::Camera*); + bool writeGeometry(const COLLADAFW::Geometry *); - bool writeImage(const COLLADAFW::Image*); + bool writeMaterial(const COLLADAFW::Material *); - bool writeLight(const COLLADAFW::Light*); + bool writeEffect(const COLLADAFW::Effect *); - bool writeSkinControllerData(const COLLADAFW::SkinControllerData*); + bool writeCamera(const COLLADAFW::Camera *); - bool writeController(const COLLADAFW::Controller*); + bool writeImage(const COLLADAFW::Image *); - bool writeFormulas(const COLLADAFW::Formulas*); + bool writeLight(const COLLADAFW::Light *); - bool writeKinematicsScene(const COLLADAFW::KinematicsScene*); + bool writeSkinControllerData(const COLLADAFW::SkinControllerData *); - /** Add element and data for UniqueId */ - bool addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags); - /** Get an extisting ExtraTags for uid */ - ExtraTags* getExtraTags(const COLLADAFW::UniqueId &uid); + bool writeController(const COLLADAFW::Controller *); - bool is_armature(COLLADAFW::Node * node); + bool writeFormulas(const COLLADAFW::Formulas *); + bool writeKinematicsScene(const COLLADAFW::KinematicsScene *); + /** Add element and data for UniqueId */ + bool addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags); + /** Get an extisting ExtraTags for uid */ + ExtraTags *getExtraTags(const COLLADAFW::UniqueId &uid); -private: - const ImportSettings *import_settings; + bool is_armature(COLLADAFW::Node *node); - /** Current import stage we're in. */ - ImportStage mImportStage; + private: + const ImportSettings *import_settings; - bContext *mContext; - ViewLayer *view_layer; + /** Current import stage we're in. */ + ImportStage mImportStage; - UnitConverter unit_converter; - ArmatureImporter armature_importer; - MeshImporter mesh_importer; - AnimationImporter anim_importer; + bContext *mContext; + ViewLayer *view_layer; - /** TagsMap typedef for uid_tags_map. */ - typedef std::map<std::string, ExtraTags*> TagsMap; - /** Tags map of unique id as a string and ExtraTags instance. */ - TagsMap uid_tags_map; + UnitConverter unit_converter; + ArmatureImporter armature_importer; + MeshImporter mesh_importer; + AnimationImporter anim_importer; - UidImageMap uid_image_map; - std::map<COLLADAFW::UniqueId, Material*> uid_material_map; - std::map<COLLADAFW::UniqueId, Material*> uid_effect_map; - std::map<COLLADAFW::UniqueId, Camera*> uid_camera_map; - std::map<COLLADAFW::UniqueId, Light*> uid_light_map; - std::map<Material*, TexIndexTextureArrayMap> material_texture_mapping_map; - std::multimap<COLLADAFW::UniqueId, Object*> object_map; - std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> node_map; - std::vector<const COLLADAFW::VisualScene*> vscenes; - std::vector<Object*> libnode_ob; + /** TagsMap typedef for uid_tags_map. */ + typedef std::map<std::string, ExtraTags *> TagsMap; + /** Tags map of unique id as a string and ExtraTags instance. */ + TagsMap uid_tags_map; - std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> root_map; // find root joint by child joint uid, for bone tree evaluation during resampling - std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map; + UidImageMap uid_image_map; + std::map<COLLADAFW::UniqueId, Material *> uid_material_map; + std::map<COLLADAFW::UniqueId, Material *> uid_effect_map; + std::map<COLLADAFW::UniqueId, Camera *> uid_camera_map; + std::map<COLLADAFW::UniqueId, Light *> uid_light_map; + std::map<Material *, TexIndexTextureArrayMap> material_texture_mapping_map; + std::multimap<COLLADAFW::UniqueId, Object *> object_map; + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> node_map; + std::vector<const COLLADAFW::VisualScene *> vscenes; + std::vector<Object *> libnode_ob; - std::string import_from_version; + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> + root_map; // find root joint by child joint uid, for bone tree evaluation during resampling + std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map; - void report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type); + std::string import_from_version; + void report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type); }; #endif diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 94e86af521f..58435c4551f 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - #include <map> #include <set> @@ -33,247 +32,251 @@ #include "collada_utils.h" extern "C" { - #include "DNA_mesh_types.h" - #include "DNA_world_types.h" +#include "DNA_mesh_types.h" +#include "DNA_world_types.h" - #include "BKE_collection.h" - #include "BKE_customdata.h" - #include "BKE_mesh.h" - #include "BKE_material.h" +#include "BKE_collection.h" +#include "BKE_customdata.h" +#include "BKE_mesh.h" +#include "BKE_material.h" } static std::string getActiveUVLayerName(Object *ob) { - Mesh *me = (Mesh *)ob->data; + Mesh *me = (Mesh *)ob->data; - int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - if (num_layers) - return std::string(bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV)); + int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); + if (num_layers) + return std::string(bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV)); - return ""; + return ""; } -EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map) : - COLLADASW::LibraryEffects(sw), - export_settings(export_settings), - key_image_map(key_image_map) -{} - +EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings, + KeyImageMap &key_image_map) + : COLLADASW::LibraryEffects(sw), export_settings(export_settings), key_image_map(key_image_map) +{ +} bool EffectsExporter::hasEffects(Scene *sce) { - FOREACH_SCENE_OBJECT_BEGIN(sce, ob) - { - int a; - for (a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); - - // no material, but check all of the slots - if (!ma) continue; - - return true; - } - } - FOREACH_SCENE_OBJECT_END; - return false; + FOREACH_SCENE_OBJECT_BEGIN (sce, ob) { + int a; + for (a = 0; a < ob->totcol; a++) { + Material *ma = give_current_material(ob, a + 1); + + // no material, but check all of the slots + if (!ma) + continue; + + return true; + } + } + FOREACH_SCENE_OBJECT_END; + return false; } void EffectsExporter::exportEffects(bContext *C, Scene *sce) { - if (hasEffects(sce)) { - this->mContext = C; - this->scene = sce; - openLibrary(); - MaterialFunctor mf; - mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); - - closeLibrary(); - } + if (hasEffects(sce)) { + this->mContext = C; + this->scene = sce; + openLibrary(); + MaterialFunctor mf; + mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); + + closeLibrary(); + } } void EffectsExporter::set_shader_type(COLLADASW::EffectProfile &ep, Material *ma) { - ep.setShaderType(COLLADASW::EffectProfile::LAMBERT); //XXX check if BLINN and PHONG can be supported as well + ep.setShaderType( + COLLADASW::EffectProfile::LAMBERT); //XXX check if BLINN and PHONG can be supported as well } void EffectsExporter::set_transparency(COLLADASW::EffectProfile &ep, Material *ma) { - COLLADASW::ColorOrTexture cot = bc_get_base_color(ma); - float transparency = cot.getColor().getAlpha(); - if (transparency < 1) { - // Tod: because we are in A_ONE mode transparency is calculated like this: - COLLADASW::ColorOrTexture cot = getcol(1.0f, 1.0f, 1.0f, transparency); - ep.setTransparent(cot); - ep.setOpaque(COLLADASW::EffectProfile::A_ONE); - } + COLLADASW::ColorOrTexture cot = bc_get_base_color(ma); + float transparency = cot.getColor().getAlpha(); + if (transparency < 1) { + // Tod: because we are in A_ONE mode transparency is calculated like this: + COLLADASW::ColorOrTexture cot = getcol(1.0f, 1.0f, 1.0f, transparency); + ep.setTransparent(cot); + ep.setOpaque(COLLADASW::EffectProfile::A_ONE); + } } void EffectsExporter::set_diffuse_color(COLLADASW::EffectProfile &ep, Material *ma) { - // get diffuse color - COLLADASW::ColorOrTexture cot = bc_get_base_color(ma); - ep.setDiffuse(cot, false, "diffuse"); + // get diffuse color + COLLADASW::ColorOrTexture cot = bc_get_base_color(ma); + ep.setDiffuse(cot, false, "diffuse"); } void EffectsExporter::set_reflectivity(COLLADASW::EffectProfile &ep, Material *ma) { - double reflectivity = bc_get_reflectivity(ma); - ep.setReflectivity(reflectivity, false, "specular"); + double reflectivity = bc_get_reflectivity(ma); + ep.setReflectivity(reflectivity, false, "specular"); } void EffectsExporter::set_emission(COLLADASW::EffectProfile &ep, Material *ma) { - // not yet supported (needs changes in principled shader + // not yet supported (needs changes in principled shader } void EffectsExporter::get_images(Material *ma, KeyImageMap &material_image_map) { - if (!ma->use_nodes) { - return; - } - - MaterialNode material = MaterialNode(mContext, ma, key_image_map); - Image *image = material.get_diffuse_image(); - if (image == nullptr) { - return; - } - - std::string uid(id_name(image)); - std::string key = translate_id(uid); - - if (material_image_map.find(key) == material_image_map.end()) { - material_image_map[key] = image; - key_image_map[key] = image; - } + if (!ma->use_nodes) { + return; + } + + MaterialNode material = MaterialNode(mContext, ma, key_image_map); + Image *image = material.get_diffuse_image(); + if (image == nullptr) { + return; + } + + std::string uid(id_name(image)); + std::string key = translate_id(uid); + + if (material_image_map.find(key) == material_image_map.end()) { + material_image_map[key] = image; + key_image_map[key] = image; + } } -void EffectsExporter::create_image_samplers(COLLADASW::EffectProfile &ep, KeyImageMap &material_image_map, std::string &active_uv) +void EffectsExporter::create_image_samplers(COLLADASW::EffectProfile &ep, + KeyImageMap &material_image_map, + std::string &active_uv) { - KeyImageMap::iterator iter; + KeyImageMap::iterator iter; - for (iter = material_image_map.begin(); iter != material_image_map.end(); iter++) { + for (iter = material_image_map.begin(); iter != material_image_map.end(); iter++) { - Image *image = iter->second; - std::string uid(id_name(image)); - std::string key = translate_id(uid); + Image *image = iter->second; + std::string uid(id_name(image)); + std::string key = translate_id(uid); - COLLADASW::Sampler *sampler = new COLLADASW::Sampler( - COLLADASW::Sampler::SAMPLER_TYPE_2D, - key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, - key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); + COLLADASW::Sampler *sampler = new COLLADASW::Sampler( + COLLADASW::Sampler::SAMPLER_TYPE_2D, + key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, + key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); - sampler->setImageId(key); + sampler->setImageId(key); - ep.setDiffuse(createTexture(image, active_uv, sampler), false, "diffuse"); - } + ep.setDiffuse(createTexture(image, active_uv, sampler), false, "diffuse"); + } } void EffectsExporter::operator()(Material *ma, Object *ob) { - KeyImageMap material_image_map; + KeyImageMap material_image_map; - openEffect(get_effect_id(ma)); + openEffect(get_effect_id(ma)); - COLLADASW::EffectProfile ep(mSW); - ep.setProfileType(COLLADASW::EffectProfile::COMMON); - ep.openProfile(); - set_shader_type(ep, ma); + COLLADASW::EffectProfile ep(mSW); + ep.setProfileType(COLLADASW::EffectProfile::COMMON); + ep.openProfile(); + set_shader_type(ep, ma); - COLLADASW::ColorOrTexture cot; + COLLADASW::ColorOrTexture cot; - set_transparency(ep, ma); - set_diffuse_color(ep, ma); - set_reflectivity(ep, ma); - set_emission(ep, ma); + set_transparency(ep, ma); + set_diffuse_color(ep, ma); + set_reflectivity(ep, ma); + set_emission(ep, ma); - get_images(ma, material_image_map); - std::string active_uv(getActiveUVLayerName(ob)); - create_image_samplers(ep, material_image_map, active_uv); + get_images(ma, material_image_map); + std::string active_uv(getActiveUVLayerName(ob)); + create_image_samplers(ep, material_image_map, active_uv); #if 0 - unsigned int a, b; - for (a = 0, b = 0; a < tex_indices.size(); a++) { - MTex *t = ma->mtex[tex_indices[a]]; - Image *ima = t->tex->ima; - - // Image not set for texture - if (!ima) continue; - - std::string key(id_name(ima)); - key = translate_id(key); - - // create only one <sampler>/<surface> pair for each unique image - if (im_samp_map.find(key) == im_samp_map.end()) { - //<newparam> <sampler> <source> - COLLADASW::Sampler sampler( - COLLADASW::Sampler::SAMPLER_TYPE_2D, - key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, - key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); - sampler.setImageId(key); - // copy values to arrays since they will live longer - samplers[a] = sampler; - - // store pointers so they can be used later when we create <texture>s - samp_surf[b] = &samplers[a]; - //samp_surf[b][1] = &surfaces[a]; - - im_samp_map[key] = b; - b++; - } - } - - for (a = 0; a < tex_indices.size(); a++) { - MTex *t = ma->mtex[tex_indices[a]]; - Image *ima = t->tex->ima; - - if (!ima) { - continue; - } - - std::string key(id_name(ima)); - key = translate_id(key); - int i = im_samp_map[key]; - std::string uvname = strlen(t->uvname) ? t->uvname : active_uv; - COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i]; // possibly uninitialised memory ... - writeTextures(ep, key, sampler, t, ima, uvname); - } + unsigned int a, b; + for (a = 0, b = 0; a < tex_indices.size(); a++) { + MTex *t = ma->mtex[tex_indices[a]]; + Image *ima = t->tex->ima; + + // Image not set for texture + if (!ima) continue; + + std::string key(id_name(ima)); + key = translate_id(key); + + // create only one <sampler>/<surface> pair for each unique image + if (im_samp_map.find(key) == im_samp_map.end()) { + //<newparam> <sampler> <source> + COLLADASW::Sampler sampler( + COLLADASW::Sampler::SAMPLER_TYPE_2D, + key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, + key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); + sampler.setImageId(key); + // copy values to arrays since they will live longer + samplers[a] = sampler; + + // store pointers so they can be used later when we create <texture>s + samp_surf[b] = &samplers[a]; + //samp_surf[b][1] = &surfaces[a]; + + im_samp_map[key] = b; + b++; + } + } + + for (a = 0; a < tex_indices.size(); a++) { + MTex *t = ma->mtex[tex_indices[a]]; + Image *ima = t->tex->ima; + + if (!ima) { + continue; + } + + std::string key(id_name(ima)); + key = translate_id(key); + int i = im_samp_map[key]; + std::string uvname = strlen(t->uvname) ? t->uvname : active_uv; + COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i]; // possibly uninitialised memory ... + writeTextures(ep, key, sampler, t, ima, uvname); + } #endif - // performs the actual writing - ep.addProfileElements(); - bool twoSided = false; - if (ob->type == OB_MESH && ob->data) { - Mesh *me = (Mesh *)ob->data; - if (me->flag & ME_TWOSIDED) - twoSided = true; - } - if (twoSided) - ep.addExtraTechniqueParameter("GOOGLEEARTH", "double_sided", 1); - ep.addExtraTechniques(mSW); - - ep.closeProfile(); - if (twoSided) - mSW->appendTextBlock("<extra><technique profile=\"MAX3D\"><double_sided>1</double_sided></technique></extra>"); - closeEffect(); + // performs the actual writing + ep.addProfileElements(); + bool twoSided = false; + if (ob->type == OB_MESH && ob->data) { + Mesh *me = (Mesh *)ob->data; + if (me->flag & ME_TWOSIDED) + twoSided = true; + } + if (twoSided) + ep.addExtraTechniqueParameter("GOOGLEEARTH", "double_sided", 1); + ep.addExtraTechniques(mSW); + + ep.closeProfile(); + if (twoSided) + mSW->appendTextBlock( + "<extra><technique profile=\"MAX3D\"><double_sided>1</double_sided></technique></extra>"); + closeEffect(); } COLLADASW::ColorOrTexture EffectsExporter::createTexture(Image *ima, - std::string& uv_layer_name, + std::string &uv_layer_name, COLLADASW::Sampler *sampler /*COLLADASW::Surface *surface*/) { - COLLADASW::Texture texture(translate_id(id_name(ima))); - texture.setTexcoord(uv_layer_name); - //texture.setSurface(*surface); - texture.setSampler(*sampler); + COLLADASW::Texture texture(translate_id(id_name(ima))); + texture.setTexcoord(uv_layer_name); + //texture.setSurface(*surface); + texture.setSampler(*sampler); - COLLADASW::ColorOrTexture cot(texture); - return cot; + COLLADASW::ColorOrTexture cot(texture); + return cot; } COLLADASW::ColorOrTexture EffectsExporter::getcol(float r, float g, float b, float a) { - COLLADASW::Color color(r, g, b, a); - COLLADASW::ColorOrTexture cot(color); - return cot; + COLLADASW::Color color(r, g, b, a); + COLLADASW::ColorOrTexture cot(color); + return cot; } diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h index 6d42a3d69ba..25df2d7eb89 100644 --- a/source/blender/collada/EffectExporter.h +++ b/source/blender/collada/EffectExporter.h @@ -37,42 +37,46 @@ #include "ExportSettings.h" #include "collada_utils.h" -class EffectsExporter: COLLADASW::LibraryEffects -{ -public: - EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map); - void exportEffects(bContext *C, Scene *sce); +class EffectsExporter : COLLADASW::LibraryEffects { + public: + EffectsExporter(COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings, + KeyImageMap &key_image_map); + void exportEffects(bContext *C, Scene *sce); - void operator()(Material *ma, Object *ob); + void operator()(Material *ma, Object *ob); - COLLADASW::ColorOrTexture createTexture(Image *ima, - std::string& uv_layer_name, - COLLADASW::Sampler *sampler - /*COLLADASW::Surface *surface*/); + COLLADASW::ColorOrTexture createTexture(Image *ima, + std::string &uv_layer_name, + COLLADASW::Sampler *sampler + /*COLLADASW::Surface *surface*/); - COLLADASW::ColorOrTexture getcol(float r, float g, float b, float a); -private: - void set_shader_type(COLLADASW::EffectProfile &ep, Material *ma); - void set_transparency(COLLADASW::EffectProfile &ep, Material *ma); - void set_diffuse_color(COLLADASW::EffectProfile &ep, Material *ma); - void set_reflectivity(COLLADASW::EffectProfile &ep, Material *ma); - void set_emission(COLLADASW::EffectProfile &ep, Material *ma); - void get_images(Material *ma, KeyImageMap &uid_image_map); - void create_image_samplers(COLLADASW::EffectProfile &ep, KeyImageMap &uid_image_map, std::string &active_uv); + COLLADASW::ColorOrTexture getcol(float r, float g, float b, float a); - void writeTextures( - COLLADASW::EffectProfile &ep, - std::string &key, - COLLADASW::Sampler *sampler, - MTex *t, Image *ima, - std::string &uvname ); + private: + void set_shader_type(COLLADASW::EffectProfile &ep, Material *ma); + void set_transparency(COLLADASW::EffectProfile &ep, Material *ma); + void set_diffuse_color(COLLADASW::EffectProfile &ep, Material *ma); + void set_reflectivity(COLLADASW::EffectProfile &ep, Material *ma); + void set_emission(COLLADASW::EffectProfile &ep, Material *ma); + void get_images(Material *ma, KeyImageMap &uid_image_map); + void create_image_samplers(COLLADASW::EffectProfile &ep, + KeyImageMap &uid_image_map, + std::string &active_uv); - bool hasEffects(Scene *sce); + void writeTextures(COLLADASW::EffectProfile &ep, + std::string &key, + COLLADASW::Sampler *sampler, + MTex *t, + Image *ima, + std::string &uvname); - const ExportSettings *export_settings; - KeyImageMap &key_image_map; - Scene *scene; - bContext *mContext; + bool hasEffects(Scene *sce); + + const ExportSettings *export_settings; + KeyImageMap &key_image_map; + Scene *scene; + bContext *mContext; }; #endif diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp index 0e1647e615f..379f54247e0 100644 --- a/source/blender/collada/ErrorHandler.cpp +++ b/source/blender/collada/ErrorHandler.cpp @@ -43,67 +43,70 @@ ErrorHandler::~ErrorHandler() //-------------------------------------------------------------------- bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) { - /* This method must return false when Collada should continue. - * See https://github.com/KhronosGroup/OpenCOLLADA/issues/442 - */ - bool isError = true; - std::string error_context; - std::string error_message; - - if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) { - error_context = "Schema validation"; - - COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error; - const GeneratedSaxParser::ParserError& parserError = saxParserError->getError(); - error_message = parserError.getErrorMessage(); - - if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_MIN_OCCURS_UNMATCHED) { - if (STREQ(parserError.getElement(), "effect")) { - isError = false; - } - } - - else if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_VALIDATION_SEQUENCE_PREVIOUS_SIBLING_NOT_PRESENT) { - if (!(STREQ(parserError.getElement(), "extra") && - STREQ(parserError.getAdditionalText().c_str(), "sibling: fx_profile_abstract"))) - { - isError = false; - } - } - - else if (parserError.getErrorType() == GeneratedSaxParser::ParserError::ERROR_COULD_NOT_OPEN_FILE) { - isError = true; - error_context = "File access"; - } - - else isError = (parserError.getSeverity() != GeneratedSaxParser::ParserError::Severity::SEVERITY_ERROR_NONCRITICAL); - - } - else if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXFWL) { - error_context = "Sax FWL"; - COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *) error; - error_message = saxFWLError->getErrorMessage(); - - /* - * Accept non critical errors as warnings (i.e. texture not found) - * This makes the importer more graceful, so it now imports what makes sense. - */ - - isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL); - - } - else { - error_context = "OpenCollada"; - error_message = error->getFullErrorMessage(); - isError = true; - } - - std::string severity = (isError) ? "Error" : "Warning"; - std::cout << error_context << " (" << severity << "): " << error_message << std::endl; - if (isError) { - std::cout << "The Collada import has been forced to stop." << std::endl; - std::cout << "Please fix the reported error and then try again."; - mError = true; - } - return isError; + /* This method must return false when Collada should continue. + * See https://github.com/KhronosGroup/OpenCOLLADA/issues/442 + */ + bool isError = true; + std::string error_context; + std::string error_message; + + if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) { + error_context = "Schema validation"; + + COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *)error; + const GeneratedSaxParser::ParserError &parserError = saxParserError->getError(); + error_message = parserError.getErrorMessage(); + + if (parserError.getErrorType() == + GeneratedSaxParser::ParserError::ERROR_VALIDATION_MIN_OCCURS_UNMATCHED) { + if (STREQ(parserError.getElement(), "effect")) { + isError = false; + } + } + + else if (parserError.getErrorType() == + GeneratedSaxParser::ParserError:: + ERROR_VALIDATION_SEQUENCE_PREVIOUS_SIBLING_NOT_PRESENT) { + if (!(STREQ(parserError.getElement(), "extra") && + STREQ(parserError.getAdditionalText().c_str(), "sibling: fx_profile_abstract"))) { + isError = false; + } + } + + else if (parserError.getErrorType() == + GeneratedSaxParser::ParserError::ERROR_COULD_NOT_OPEN_FILE) { + isError = true; + error_context = "File access"; + } + + else + isError = (parserError.getSeverity() != + GeneratedSaxParser::ParserError::Severity::SEVERITY_ERROR_NONCRITICAL); + } + else if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXFWL) { + error_context = "Sax FWL"; + COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *)error; + error_message = saxFWLError->getErrorMessage(); + + /* + * Accept non critical errors as warnings (i.e. texture not found) + * This makes the importer more graceful, so it now imports what makes sense. + */ + + isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL); + } + else { + error_context = "OpenCollada"; + error_message = error->getFullErrorMessage(); + isError = true; + } + + std::string severity = (isError) ? "Error" : "Warning"; + std::cout << error_context << " (" << severity << "): " << error_message << std::endl; + if (isError) { + std::cout << "The Collada import has been forced to stop." << std::endl; + std::cout << "Please fix the reported error and then try again."; + mError = true; + } + return isError; } diff --git a/source/blender/collada/ErrorHandler.h b/source/blender/collada/ErrorHandler.h index f32f1d60a6a..5851e5da67b 100644 --- a/source/blender/collada/ErrorHandler.h +++ b/source/blender/collada/ErrorHandler.h @@ -21,29 +21,32 @@ #include <string> #include <map> #include <vector> -#include <algorithm> // sort() +#include <algorithm> // sort() #include "COLLADASaxFWLIErrorHandler.h" /** \brief Handler class for parser errors */ -class ErrorHandler : public COLLADASaxFWL::IErrorHandler -{ -public: - /** Constructor. */ - ErrorHandler(); +class ErrorHandler : public COLLADASaxFWL::IErrorHandler { + public: + /** Constructor. */ + ErrorHandler(); - /** Destructor. */ - virtual ~ErrorHandler(); - /** handle any error thrown by the parser. */ - bool virtual handleError(const COLLADASaxFWL::IError* error); - /** True if there was an error during parsing. */ - bool hasError() { return mError; } -private: - /** Disable default copy ctor. */ - ErrorHandler(const ErrorHandler& pre); - /** Disable default assignment operator. */ - const ErrorHandler& operator= ( const ErrorHandler& pre ); - /** Hold error status. */ - bool mError; + /** Destructor. */ + virtual ~ErrorHandler(); + /** handle any error thrown by the parser. */ + bool virtual handleError(const COLLADASaxFWL::IError *error); + /** True if there was an error during parsing. */ + bool hasError() + { + return mError; + } + + private: + /** Disable default copy ctor. */ + ErrorHandler(const ErrorHandler &pre); + /** Disable default assignment operator. */ + const ErrorHandler &operator=(const ErrorHandler &pre); + /** Hold error status. */ + bool mError; }; diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 43dccef658b..a362b72be00 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -28,61 +28,60 @@ extern "C" { #include "BLI_linklist.h" typedef enum BC_export_mesh_type { - BC_MESH_TYPE_VIEW, - BC_MESH_TYPE_RENDER, + BC_MESH_TYPE_VIEW, + BC_MESH_TYPE_RENDER, } BC_export_mesh_type; typedef enum BC_export_transformation_type { - BC_TRANSFORMATION_TYPE_MATRIX, - BC_TRANSFORMATION_TYPE_TRANSROTLOC, + BC_TRANSFORMATION_TYPE_MATRIX, + BC_TRANSFORMATION_TYPE_TRANSROTLOC, } BC_export_transformation_type; - typedef enum BC_export_animation_type { - BC_ANIMATION_EXPORT_SAMPLES, - BC_ANIMATION_EXPORT_KEYS, + BC_ANIMATION_EXPORT_SAMPLES, + BC_ANIMATION_EXPORT_KEYS, } BC_export_animation_type; typedef enum BC_ui_export_section { - BC_UI_SECTION_MAIN, - BC_UI_SECTION_GEOMETRY, - BC_UI_SECTION_ARMATURE, - BC_UI_SECTION_ANIMATION, - BC_UI_SECTION_COLLADA, + BC_UI_SECTION_MAIN, + BC_UI_SECTION_GEOMETRY, + BC_UI_SECTION_ARMATURE, + BC_UI_SECTION_ANIMATION, + BC_UI_SECTION_COLLADA, } BC_ui_export_section; typedef struct ExportSettings { - bool apply_modifiers; - BC_export_mesh_type export_mesh_type; - - bool selected; - bool include_children; - bool include_armatures; - bool include_shapekeys; - bool deform_bones_only; - bool include_animations; - bool include_all_actions; - int sampling_rate; - bool keep_smooth_curves; - bool keep_keyframes; - bool keep_flat_curves; - - bool active_uv_only; - BC_export_animation_type export_animation_type; - bool use_texture_copies; - - bool triangulate; - bool use_object_instantiation; - bool use_blender_profile; - bool sort_by_name; - BC_export_transformation_type export_transformation_type; - - bool open_sim; - bool limit_precision; - bool keep_bind_info; - - char *filepath; - LinkNode *export_set; + bool apply_modifiers; + BC_export_mesh_type export_mesh_type; + + bool selected; + bool include_children; + bool include_armatures; + bool include_shapekeys; + bool deform_bones_only; + bool include_animations; + bool include_all_actions; + int sampling_rate; + bool keep_smooth_curves; + bool keep_keyframes; + bool keep_flat_curves; + + bool active_uv_only; + BC_export_animation_type export_animation_type; + bool use_texture_copies; + + bool triangulate; + bool use_object_instantiation; + bool use_blender_profile; + bool sort_by_name; + BC_export_transformation_type export_transformation_type; + + bool open_sim; + bool limit_precision; + bool keep_bind_info; + + char *filepath; + LinkNode *export_set; } ExportSettings; #ifdef __cplusplus diff --git a/source/blender/collada/ExtraHandler.cpp b/source/blender/collada/ExtraHandler.cpp index 48586a2b169..5aed0050a06 100644 --- a/source/blender/collada/ExtraHandler.cpp +++ b/source/blender/collada/ExtraHandler.cpp @@ -25,64 +25,63 @@ ExtraHandler::ExtraHandler(DocumentImporter *dimp, AnimationImporter *aimp) : currentExtraTags(0) { - this->dimp = dimp; - this->aimp = aimp; + this->dimp = dimp; + this->aimp = aimp; } -ExtraHandler::~ExtraHandler() { +ExtraHandler::~ExtraHandler() +{ } bool ExtraHandler::elementBegin(const char *elementName, const char **attributes) { - // \todo attribute handling for profile tags - currentElement = std::string(elementName); - //addToSidTree(attributes[0], attributes[1]); - return true; + // \todo attribute handling for profile tags + currentElement = std::string(elementName); + //addToSidTree(attributes[0], attributes[1]); + return true; } bool ExtraHandler::elementEnd(const char *elementName) { - return true; + return true; } bool ExtraHandler::textData(const char *text, size_t textLength) { - char buf[1024]; + char buf[1024]; - if (currentElement.length() == 0 || currentExtraTags == 0) return false; + if (currentElement.length() == 0 || currentExtraTags == 0) + return false; - BLI_strncpy(buf, text, textLength + 1); - currentExtraTags->addTag(currentElement, std::string(buf)); - return true; + BLI_strncpy(buf, text, textLength + 1); + currentExtraTags->addTag(currentElement, std::string(buf)); + return true; } -bool ExtraHandler::parseElement( - const char *profileName, - const unsigned long& elementHash, - const COLLADAFW::UniqueId& uniqueId) +bool ExtraHandler::parseElement(const char *profileName, + const unsigned long &elementHash, + const COLLADAFW::UniqueId &uniqueId) { - /* implement for backwards compatibility, new version added object parameter */ - return parseElement(profileName, elementHash, uniqueId, NULL); + /* implement for backwards compatibility, new version added object parameter */ + return parseElement(profileName, elementHash, uniqueId, NULL); } -bool ExtraHandler::parseElement( - const char *profileName, - const unsigned long& elementHash, - const COLLADAFW::UniqueId& uniqueId, - COLLADAFW::Object* object) +bool ExtraHandler::parseElement(const char *profileName, + const unsigned long &elementHash, + const COLLADAFW::UniqueId &uniqueId, + COLLADAFW::Object *object) { - if (BLI_strcaseeq(profileName, "blender")) { - //printf("In parseElement for supported profile %s for id %s\n", profileName, uniqueId.toAscii().c_str()); - currentUid = uniqueId; - ExtraTags *et = dimp->getExtraTags(uniqueId); - if (!et) { - et = new ExtraTags(std::string(profileName)); - dimp->addExtraTags(uniqueId, et); - - } - currentExtraTags = et; - return true; - } - //printf("In parseElement for unsupported profile %s for id %s\n", profileName, uniqueId.toAscii().c_str()); - return false; + if (BLI_strcaseeq(profileName, "blender")) { + //printf("In parseElement for supported profile %s for id %s\n", profileName, uniqueId.toAscii().c_str()); + currentUid = uniqueId; + ExtraTags *et = dimp->getExtraTags(uniqueId); + if (!et) { + et = new ExtraTags(std::string(profileName)); + dimp->addExtraTags(uniqueId, et); + } + currentExtraTags = et; + return true; + } + //printf("In parseElement for unsupported profile %s for id %s\n", profileName, uniqueId.toAscii().c_str()); + return false; } diff --git a/source/blender/collada/ExtraHandler.h b/source/blender/collada/ExtraHandler.h index fef1d5c9b7f..8203b364953 100644 --- a/source/blender/collada/ExtraHandler.h +++ b/source/blender/collada/ExtraHandler.h @@ -21,7 +21,7 @@ #include <string> #include <map> #include <vector> -#include <algorithm> // sort() +#include <algorithm> // sort() #include "COLLADASaxFWLIExtraDataCallbackHandler.h" #include "COLLADASaxFWLFilePartLoader.h" @@ -33,47 +33,45 @@ /** \brief Handler class for \<extra\> data, through which different * profiles can be handled */ -class ExtraHandler : public COLLADASaxFWL::IExtraDataCallbackHandler -{ -public: - /** Constructor. */ - ExtraHandler(DocumentImporter *dimp, AnimationImporter *aimp); +class ExtraHandler : public COLLADASaxFWL::IExtraDataCallbackHandler { + public: + /** Constructor. */ + ExtraHandler(DocumentImporter *dimp, AnimationImporter *aimp); - /** Destructor. */ - virtual ~ExtraHandler(); + /** Destructor. */ + virtual ~ExtraHandler(); - /** Handle the beginning of an element. */ - bool elementBegin( const char* elementName, const char** attributes); + /** Handle the beginning of an element. */ + bool elementBegin(const char *elementName, const char **attributes); - /** Handle the end of an element. */ - bool elementEnd(const char* elementName ); + /** Handle the end of an element. */ + bool elementEnd(const char *elementName); - /** Receive the data in text format. */ - bool textData(const char* text, size_t textLength); + /** Receive the data in text format. */ + bool textData(const char *text, size_t textLength); - /** Method to ask, if the current callback handler want to read the data of the given extra element. */ - bool parseElement ( - const char* profileName, - const unsigned long& elementHash, - const COLLADAFW::UniqueId& uniqueId, - COLLADAFW::Object* object); + /** Method to ask, if the current callback handler want to read the data of the given extra element. */ + bool parseElement(const char *profileName, + const unsigned long &elementHash, + const COLLADAFW::UniqueId &uniqueId, + COLLADAFW::Object *object); - /** For backwards compatibility with older OpenCollada, new version added object parameter */ - bool parseElement ( - const char* profileName, - const unsigned long& elementHash, - const COLLADAFW::UniqueId& uniqueId); -private: - /** Disable default copy constructor. */ - ExtraHandler(const ExtraHandler& pre); - /** Disable default assignment operator. */ - const ExtraHandler& operator= ( const ExtraHandler& pre ); + /** For backwards compatibility with older OpenCollada, new version added object parameter */ + bool parseElement(const char *profileName, + const unsigned long &elementHash, + const COLLADAFW::UniqueId &uniqueId); - /** Handle to DocumentImporter for interface to extra element data saving. */ - DocumentImporter* dimp; - AnimationImporter* aimp; - /** Holds Id of element for which <extra> XML elements are handled. */ - COLLADAFW::UniqueId currentUid; - ExtraTags* currentExtraTags; - std::string currentElement; + private: + /** Disable default copy constructor. */ + ExtraHandler(const ExtraHandler &pre); + /** Disable default assignment operator. */ + const ExtraHandler &operator=(const ExtraHandler &pre); + + /** Handle to DocumentImporter for interface to extra element data saving. */ + DocumentImporter *dimp; + AnimationImporter *aimp; + /** Holds Id of element for which <extra> XML elements are handled. */ + COLLADAFW::UniqueId currentUid; + ExtraTags *currentExtraTags; + std::string currentElement; }; diff --git a/source/blender/collada/ExtraTags.cpp b/source/blender/collada/ExtraTags.cpp index 829bb40b1f5..4da0725f380 100644 --- a/source/blender/collada/ExtraTags.cpp +++ b/source/blender/collada/ExtraTags.cpp @@ -28,8 +28,8 @@ ExtraTags::ExtraTags(std::string profile) { - this->profile = profile; - this->tags = std::map<std::string, std::string>(); + this->profile = profile; + this->tags = std::map<std::string, std::string>(); } ExtraTags::~ExtraTags() @@ -38,86 +38,85 @@ ExtraTags::~ExtraTags() bool ExtraTags::isProfile(std::string profile) { - return this->profile == profile; + return this->profile == profile; } -bool ExtraTags::addTag(std::string tag, std::string data) +bool ExtraTags::addTag(std::string tag, std::string data) { - tags[tag] = data; + tags[tag] = data; - return true; + return true; } int ExtraTags::asInt(std::string tag, bool *ok) { - if (tags.find(tag) == tags.end()) { - *ok = false; - return -1; - } - *ok = true; - return atoi(tags[tag].c_str()); + if (tags.find(tag) == tags.end()) { + *ok = false; + return -1; + } + *ok = true; + return atoi(tags[tag].c_str()); } float ExtraTags::asFloat(std::string tag, bool *ok) { - if (tags.find(tag) == tags.end()) { - *ok = false; - return -1.0f; - } - *ok = true; - return (float)atof(tags[tag].c_str()); + if (tags.find(tag) == tags.end()) { + *ok = false; + return -1.0f; + } + *ok = true; + return (float)atof(tags[tag].c_str()); } std::string ExtraTags::asString(std::string tag, bool *ok) { - if (tags.find(tag) == tags.end()) { - *ok = false; - return ""; - } - *ok = true; - return tags[tag]; + if (tags.find(tag) == tags.end()) { + *ok = false; + return ""; + } + *ok = true; + return tags[tag]; } - bool ExtraTags::setData(std::string tag, short *data) { - bool ok = false; - int tmp = asInt(tag, &ok); - if (ok) - *data = (short)tmp; - return ok; + bool ok = false; + int tmp = asInt(tag, &ok); + if (ok) + *data = (short)tmp; + return ok; } bool ExtraTags::setData(std::string tag, int *data) { - bool ok = false; - int tmp = asInt(tag, &ok); - if (ok) - *data = tmp; - return ok; + bool ok = false; + int tmp = asInt(tag, &ok); + if (ok) + *data = tmp; + return ok; } bool ExtraTags::setData(std::string tag, float *data) { - bool ok = false; - float tmp = asFloat(tag, &ok); - if (ok) - *data = tmp; - return ok; + bool ok = false; + float tmp = asFloat(tag, &ok); + if (ok) + *data = tmp; + return ok; } bool ExtraTags::setData(std::string tag, char *data) { - bool ok = false; - int tmp = asInt(tag, &ok); - if (ok) - *data = (char)tmp; - return ok; + bool ok = false; + int tmp = asInt(tag, &ok); + if (ok) + *data = (char)tmp; + return ok; } std::string ExtraTags::setData(std::string tag, std::string &data) { - bool ok = false; - std::string tmp = asString(tag, &ok); - return (ok) ? tmp : data; + bool ok = false; + std::string tmp = asString(tag, &ok); + return (ok) ? tmp : data; } diff --git a/source/blender/collada/ExtraTags.h b/source/blender/collada/ExtraTags.h index e7c574751b9..2d827159af8 100644 --- a/source/blender/collada/ExtraTags.h +++ b/source/blender/collada/ExtraTags.h @@ -24,50 +24,49 @@ /** \brief Class for saving \<extra\> tags for a specific UniqueId. */ -class ExtraTags -{ -public: - /** Constructor. */ - ExtraTags(const std::string profile); +class ExtraTags { + public: + /** Constructor. */ + ExtraTags(const std::string profile); - /** Destructor. */ - virtual ~ExtraTags(); + /** Destructor. */ + virtual ~ExtraTags(); - /** Handle the beginning of an element. */ - bool addTag(std::string tag, std::string data); + /** Handle the beginning of an element. */ + bool addTag(std::string tag, std::string data); - /** Set given short pointer to value of tag, if it exists. */ - bool setData(std::string tag, short *data); + /** Set given short pointer to value of tag, if it exists. */ + bool setData(std::string tag, short *data); - /** Set given int pointer to value of tag, if it exists. */ - bool setData(std::string tag, int *data); + /** Set given int pointer to value of tag, if it exists. */ + bool setData(std::string tag, int *data); - /** Set given float pointer to value of tag, if it exists. */ - bool setData(std::string tag, float *data); + /** Set given float pointer to value of tag, if it exists. */ + bool setData(std::string tag, float *data); - /** Set given char pointer to value of tag, if it exists. */ - bool setData(std::string tag, char *data); - std::string setData(std::string tag, std::string &data); + /** Set given char pointer to value of tag, if it exists. */ + bool setData(std::string tag, char *data); + std::string setData(std::string tag, std::string &data); - /** Return true if the extra tags is for specified profile. */ - bool isProfile(std::string profile); + /** Return true if the extra tags is for specified profile. */ + bool isProfile(std::string profile); -private: - /** Disable default copy constructor. */ - ExtraTags(const ExtraTags& pre); - /** Disable default assignment operator. */ - const ExtraTags& operator= ( const ExtraTags& pre ); + private: + /** Disable default copy constructor. */ + ExtraTags(const ExtraTags &pre); + /** Disable default assignment operator. */ + const ExtraTags &operator=(const ExtraTags &pre); - /** The profile for which the tags are. */ - std::string profile; + /** The profile for which the tags are. */ + std::string profile; - /** Map of tag and text pairs. */ - std::map<std::string, std::string> tags; + /** Map of tag and text pairs. */ + std::map<std::string, std::string> tags; - /** Get text data for tag as an int. */ - int asInt(std::string tag, bool *ok); - /** Get text data for tag as a float. */ - float asFloat(std::string tag, bool *ok); - /** Get text data for tag as a string. */ - std::string asString(std::string tag, bool *ok); + /** Get text data for tag as an int. */ + int asInt(std::string tag, bool *ok); + /** Get text data for tag as a float. */ + float asFloat(std::string tag, bool *ok); + /** Get text data for tag as a string. */ + std::string asString(std::string tag, bool *ok); }; diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index f589e99f84b..41452f9f35a 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - #include <sstream> #include "COLLADASWPrimitves.h" @@ -31,680 +30,682 @@ #include "DNA_meshdata_types.h" extern "C" { - #include "BLI_utildefines.h" +#include "BLI_utildefines.h" - #include "BKE_customdata.h" - #include "BKE_global.h" - #include "BKE_library.h" - #include "BKE_material.h" - #include "BKE_mesh.h" +#include "BKE_customdata.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_material.h" +#include "BKE_mesh.h" } #include "collada_internal.h" #include "collada_utils.h" - void GeometryExporter::exportGeom() { - Scene *sce = blender_context.get_scene(); - openLibrary(); + Scene *sce = blender_context.get_scene(); + openLibrary(); - GeometryFunctor gf; - gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set); + GeometryFunctor gf; + gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set); - closeLibrary(); + closeLibrary(); } void GeometryExporter::operator()(Object *ob) { - bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me = bc_get_mesh_copy( - blender_context, - ob, - this->export_settings->export_mesh_type, - this->export_settings->apply_modifiers, - this->export_settings->triangulate); - - std::string geom_id = get_geometry_id(ob, use_instantiation); - std::vector<Normal> nor; - std::vector<BCPolygonNormalsIndices> norind; - - // Skip if linked geometry was already exported from another reference - if (use_instantiation && - exportedGeometry.find(geom_id) != exportedGeometry.end()) - { - return; - } - - std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob); - geom_name = encode_xml(geom_name); - - exportedGeometry.insert(geom_id); - - bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); - - create_normals(nor, norind, me); - - // openMesh(geoId, geoName, meshId) - openMesh(geom_id, geom_name); - - // writes <source> for vertex coords - createVertsSource(geom_id, me); - - // writes <source> for normal coords - createNormalsSource(geom_id, me, nor); - - bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV); - - // writes <source> for uv coords if mesh has uv coords - if (has_uvs) { - createTexcoordsSource(geom_id, me); - } - - if (has_color) { - createVertexColorSource(geom_id, me); - } - // <vertices> - - COLLADASW::Vertices verts(mSW); - verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX)); - COLLADASW::InputList &input_list = verts.getInputList(); - COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); - input_list.push_back(input); - verts.add(); - - createLooseEdgeList(ob, me, geom_id); - - // Only create Polylists if number of faces > 0 - if (me->totface > 0) { - // XXX slow - if (ob->totcol) { - for (int a = 0; a < ob->totcol; a++) { - create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind); - } - } - else { - create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind); - } - } - - closeMesh(); - - if (me->flag & ME_TWOSIDED) { - mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>"); - } - - closeGeometry(); - - if (this->export_settings->include_shapekeys) { - Key *key = BKE_key_from_object(ob); - if (key) { - KeyBlock *kb = (KeyBlock *)key->block.first; - //skip the basis - kb = kb->next; - for (; kb; kb = kb->next) { - BKE_keyblock_convert_to_mesh(kb, me); - export_key_mesh(ob, me, kb); - } - } - } - - BKE_id_free(NULL, me); + bool use_instantiation = this->export_settings->use_object_instantiation; + Mesh *me = bc_get_mesh_copy(blender_context, + ob, + this->export_settings->export_mesh_type, + this->export_settings->apply_modifiers, + this->export_settings->triangulate); + + std::string geom_id = get_geometry_id(ob, use_instantiation); + std::vector<Normal> nor; + std::vector<BCPolygonNormalsIndices> norind; + + // Skip if linked geometry was already exported from another reference + if (use_instantiation && exportedGeometry.find(geom_id) != exportedGeometry.end()) { + return; + } + + std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob); + geom_name = encode_xml(geom_name); + + exportedGeometry.insert(geom_id); + + bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); + + create_normals(nor, norind, me); + + // openMesh(geoId, geoName, meshId) + openMesh(geom_id, geom_name); + + // writes <source> for vertex coords + createVertsSource(geom_id, me); + + // writes <source> for normal coords + createNormalsSource(geom_id, me, nor); + + bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV); + + // writes <source> for uv coords if mesh has uv coords + if (has_uvs) { + createTexcoordsSource(geom_id, me); + } + + if (has_color) { + createVertexColorSource(geom_id, me); + } + // <vertices> + + COLLADASW::Vertices verts(mSW); + verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX)); + COLLADASW::InputList &input_list = verts.getInputList(); + COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, + getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); + input_list.push_back(input); + verts.add(); + + createLooseEdgeList(ob, me, geom_id); + + // Only create Polylists if number of faces > 0 + if (me->totface > 0) { + // XXX slow + if (ob->totcol) { + for (int a = 0; a < ob->totcol; a++) { + create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind); + } + } + else { + create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind); + } + } + + closeMesh(); + + if (me->flag & ME_TWOSIDED) { + mSW->appendTextBlock( + "<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>"); + } + + closeGeometry(); + + if (this->export_settings->include_shapekeys) { + Key *key = BKE_key_from_object(ob); + if (key) { + KeyBlock *kb = (KeyBlock *)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + BKE_keyblock_convert_to_mesh(kb, me); + export_key_mesh(ob, me, kb); + } + } + } + + BKE_id_free(NULL, me); } void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb) { - std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name); - std::vector<Normal> nor; - std::vector<BCPolygonNormalsIndices> norind; + std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name); + std::vector<Normal> nor; + std::vector<BCPolygonNormalsIndices> norind; - if (exportedGeometry.find(geom_id) != exportedGeometry.end()) - { - return; - } + if (exportedGeometry.find(geom_id) != exportedGeometry.end()) { + return; + } - std::string geom_name = kb->name; + std::string geom_name = kb->name; - exportedGeometry.insert(geom_id); + exportedGeometry.insert(geom_id); - bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); + bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); - create_normals(nor, norind, me); + create_normals(nor, norind, me); - // openMesh(geoId, geoName, meshId) - openMesh(geom_id, geom_name); + // openMesh(geoId, geoName, meshId) + openMesh(geom_id, geom_name); - // writes <source> for vertex coords - createVertsSource(geom_id, me); + // writes <source> for vertex coords + createVertsSource(geom_id, me); - // writes <source> for normal coords - createNormalsSource(geom_id, me, nor); + // writes <source> for normal coords + createNormalsSource(geom_id, me, nor); - bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV); + bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV); - // writes <source> for uv coords if mesh has uv coords - if (has_uvs) { - createTexcoordsSource(geom_id, me); - } + // writes <source> for uv coords if mesh has uv coords + if (has_uvs) { + createTexcoordsSource(geom_id, me); + } - if (has_color) { - createVertexColorSource(geom_id, me); - } + if (has_color) { + createVertexColorSource(geom_id, me); + } - // <vertices> + // <vertices> - COLLADASW::Vertices verts(mSW); - verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX)); - COLLADASW::InputList &input_list = verts.getInputList(); - COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); - input_list.push_back(input); - verts.add(); + COLLADASW::Vertices verts(mSW); + verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX)); + COLLADASW::InputList &input_list = verts.getInputList(); + COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, + getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); + input_list.push_back(input); + verts.add(); - //createLooseEdgeList(ob, me, geom_id, norind); + //createLooseEdgeList(ob, me, geom_id, norind); - // XXX slow - if (ob->totcol) { - for (int a = 0; a < ob->totcol; a++) { - create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind); - } - } - else { - create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind); - } + // XXX slow + if (ob->totcol) { + for (int a = 0; a < ob->totcol; a++) { + create_mesh_primitive_list(a, has_uvs, has_color, ob, me, geom_id, norind); + } + } + else { + create_mesh_primitive_list(0, has_uvs, has_color, ob, me, geom_id, norind); + } - closeMesh(); + closeMesh(); - if (me->flag & ME_TWOSIDED) { - mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>"); - } + if (me->flag & ME_TWOSIDED) { + mSW->appendTextBlock( + "<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>"); + } - closeGeometry(); + closeGeometry(); } -void GeometryExporter::createLooseEdgeList(Object *ob, - Mesh *me, - std::string& geom_id) +void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, std::string &geom_id) { - MEdge *medges = me->medge; - int totedges = me->totedge; - int edges_in_linelist = 0; - std::vector<unsigned int> edge_list; - int index; - - // Find all loose edges in Mesh - // and save vertex indices in edge_list - for (index = 0; index < totedges; index++) - { - MEdge *edge = &medges[index]; - - if (edge->flag & ME_LOOSEEDGE) - { - edges_in_linelist += 1; - edge_list.push_back(edge->v1); - edge_list.push_back(edge->v2); - } - } - - if (edges_in_linelist > 0) - { - // Create the list of loose edges - COLLADASW::Lines lines(mSW); - - lines.setCount(edges_in_linelist); - - - COLLADASW::InputList &til = lines.getInputList(); - - // creates <input> in <lines> for vertices - COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0); - til.push_back(input1); - - lines.prepareToAppendValues(); - - for (index = 0; index < edges_in_linelist; index++) - { - lines.appendValues(edge_list[2 * index + 1]); - lines.appendValues(edge_list[2 * index]); - } - lines.finish(); - } - + MEdge *medges = me->medge; + int totedges = me->totedge; + int edges_in_linelist = 0; + std::vector<unsigned int> edge_list; + int index; + + // Find all loose edges in Mesh + // and save vertex indices in edge_list + for (index = 0; index < totedges; index++) { + MEdge *edge = &medges[index]; + + if (edge->flag & ME_LOOSEEDGE) { + edges_in_linelist += 1; + edge_list.push_back(edge->v1); + edge_list.push_back(edge->v2); + } + } + + if (edges_in_linelist > 0) { + // Create the list of loose edges + COLLADASW::Lines lines(mSW); + + lines.setCount(edges_in_linelist); + + COLLADASW::InputList &til = lines.getInputList(); + + // creates <input> in <lines> for vertices + COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, + getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), + 0); + til.push_back(input1); + + lines.prepareToAppendValues(); + + for (index = 0; index < edges_in_linelist; index++) { + lines.appendValues(edge_list[2 * index + 1]); + lines.appendValues(edge_list[2 * index]); + } + lines.finish(); + } } -static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase &primitive_list, std::vector<unsigned long> &vcount_list) +static void prepareToAppendValues(bool is_triangulated, + COLLADASW::PrimitivesBase &primitive_list, + std::vector<unsigned long> &vcount_list) { - // performs the actual writing - if (is_triangulated) { - ((COLLADASW::Triangles &)primitive_list).prepareToAppendValues(); - } - else { - // sets <vcount> - primitive_list.setVCountList(vcount_list); - ((COLLADASW::Polylist &)primitive_list).prepareToAppendValues(); - } + // performs the actual writing + if (is_triangulated) { + ((COLLADASW::Triangles &)primitive_list).prepareToAppendValues(); + } + else { + // sets <vcount> + primitive_list.setVCountList(vcount_list); + ((COLLADASW::Polylist &)primitive_list).prepareToAppendValues(); + } } -static void finish_and_delete_primitive_List(bool is_triangulated, COLLADASW::PrimitivesBase *primitive_list) +static void finish_and_delete_primitive_List(bool is_triangulated, + COLLADASW::PrimitivesBase *primitive_list) { - if (is_triangulated) { - ((COLLADASW::Triangles *)primitive_list)->finish(); - } - else { - ((COLLADASW::Polylist *)primitive_list)->finish(); - } - delete primitive_list; + if (is_triangulated) { + ((COLLADASW::Triangles *)primitive_list)->finish(); + } + else { + ((COLLADASW::Polylist *)primitive_list)->finish(); + } + delete primitive_list; } -static COLLADASW::PrimitivesBase *create_primitive_list(bool is_triangulated, COLLADASW::StreamWriter *mSW) +static COLLADASW::PrimitivesBase *create_primitive_list(bool is_triangulated, + COLLADASW::StreamWriter *mSW) { - COLLADASW::PrimitivesBase *primitive_list; - - if (is_triangulated) - { - primitive_list = new COLLADASW::Triangles(mSW); - } - else { - primitive_list = new COLLADASW::Polylist(mSW); - } - return primitive_list; + COLLADASW::PrimitivesBase *primitive_list; + + if (is_triangulated) { + primitive_list = new COLLADASW::Triangles(mSW); + } + else { + primitive_list = new COLLADASW::Polylist(mSW); + } + return primitive_list; } -static bool collect_vertex_counts_per_poly(Mesh *me, int material_index, std::vector<unsigned long> &vcount_list) +static bool collect_vertex_counts_per_poly(Mesh *me, + int material_index, + std::vector<unsigned long> &vcount_list) { - MPoly *mpolys = me->mpoly; - int totpolys = me->totpoly; - bool is_triangulated = true; - - int i; - // Expecting that p->mat_nr is always 0 if the mesh has no materials assigned - for (i = 0; i < totpolys; i++) { - MPoly *p = &mpolys[i]; - if (p->mat_nr == material_index) { - int vertex_count = p->totloop; - vcount_list.push_back(vertex_count); - if (vertex_count != 3) - is_triangulated = false; - } - } - return is_triangulated; + MPoly *mpolys = me->mpoly; + int totpolys = me->totpoly; + bool is_triangulated = true; + + int i; + // Expecting that p->mat_nr is always 0 if the mesh has no materials assigned + for (i = 0; i < totpolys; i++) { + MPoly *p = &mpolys[i]; + if (p->mat_nr == material_index) { + int vertex_count = p->totloop; + vcount_list.push_back(vertex_count); + if (vertex_count != 3) + is_triangulated = false; + } + } + return is_triangulated; } -std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char *layer_name) +std::string GeometryExporter::makeVertexColorSourceId(std::string &geom_id, char *layer_name) { - std::string result = getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + "-" + layer_name; - return result; + std::string result = getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + "-" + + layer_name; + return result; } // powerful because it handles both cases when there is material and when there's not void GeometryExporter::create_mesh_primitive_list(short material_index, - bool has_uvs, - bool has_color, - Object *ob, - Mesh *me, - std::string& geom_id, - std::vector<BCPolygonNormalsIndices>& norind) + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string &geom_id, + std::vector<BCPolygonNormalsIndices> &norind) { - MPoly *mpolys = me->mpoly; - MLoop *mloops = me->mloop; - int totpolys = me->totpoly; - - std::vector<unsigned long> vcount_list; - - bool is_triangulated = collect_vertex_counts_per_poly(me, material_index, vcount_list); - int polygon_count = vcount_list.size(); - - // no faces using this material - if (polygon_count == 0) { - fprintf(stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index); - return; - } - - Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL; - COLLADASW::PrimitivesBase *primitive_list = create_primitive_list(is_triangulated, mSW); - - // sets count attribute in <polylist> - primitive_list->setCount(polygon_count); - - // sets material name - if (ma) { - std::string material_id = get_material_id(ma); - std::ostringstream ostr; - ostr << translate_id(material_id); - primitive_list->setMaterial(ostr.str()); - } - - COLLADASW::Input vertex_input(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0); - COLLADASW::Input normals_input(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1); - - COLLADASW::InputList &til = primitive_list->getInputList(); - til.push_back(vertex_input); - til.push_back(normals_input); - - // if mesh has uv coords writes <input> for TEXCOORD - int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); - for (int i = 0; i < num_layers; i++) { - int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, i); - if (!this->export_settings->active_uv_only || layer_index == active_uv_index) { - - // char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, i); - COLLADASW::Input texcoord_input(COLLADASW::InputSemantic::TEXCOORD, - makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)), - 2, // this is only until we have optimized UV sets - (this->export_settings->active_uv_only) ? 0 : layer_index-1 //set (0,1,2,...) - ); - til.push_back(texcoord_input); - } - } - - int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); - if (totlayer_mcol > 0) { - int map_index = 0; - - for (int a = 0; a < totlayer_mcol; a++) { - char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); - COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, - makeUrl(makeVertexColorSourceId(geom_id, layer_name)), - (has_uvs) ? 3 : 2, // all color layers have same index order - map_index // set number equals color map index - ); - til.push_back(input4); - map_index++; - } - } - - // performs the actual writing - prepareToAppendValues(is_triangulated, *primitive_list, vcount_list); - - // <p> - int texindex = 0; - for (int i = 0; i < totpolys; i++) { - MPoly *p = &mpolys[i]; - int loop_count = p->totloop; - - if (p->mat_nr == material_index) { - MLoop *l = &mloops[p->loopstart]; - BCPolygonNormalsIndices normal_indices = norind[i]; - - for (int j = 0; j < loop_count; j++) { - primitive_list->appendValues(l[j].v); - primitive_list->appendValues(normal_indices[j]); - if (has_uvs) - primitive_list->appendValues(texindex + j); - - if (has_color) - primitive_list->appendValues(texindex + j); - } - } - - texindex += loop_count; - } - - finish_and_delete_primitive_List(is_triangulated, primitive_list); + MPoly *mpolys = me->mpoly; + MLoop *mloops = me->mloop; + int totpolys = me->totpoly; + + std::vector<unsigned long> vcount_list; + + bool is_triangulated = collect_vertex_counts_per_poly(me, material_index, vcount_list); + int polygon_count = vcount_list.size(); + + // no faces using this material + if (polygon_count == 0) { + fprintf( + stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index); + return; + } + + Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL; + COLLADASW::PrimitivesBase *primitive_list = create_primitive_list(is_triangulated, mSW); + + // sets count attribute in <polylist> + primitive_list->setCount(polygon_count); + + // sets material name + if (ma) { + std::string material_id = get_material_id(ma); + std::ostringstream ostr; + ostr << translate_id(material_id); + primitive_list->setMaterial(ostr.str()); + } + + COLLADASW::Input vertex_input(COLLADASW::InputSemantic::VERTEX, + getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), + 0); + COLLADASW::Input normals_input(COLLADASW::InputSemantic::NORMAL, + getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), + 1); + + COLLADASW::InputList &til = primitive_list->getInputList(); + til.push_back(vertex_input); + til.push_back(normals_input); + + // if mesh has uv coords writes <input> for TEXCOORD + int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); + int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); + for (int i = 0; i < num_layers; i++) { + int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, i); + if (!this->export_settings->active_uv_only || layer_index == active_uv_index) { + + // char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, i); + COLLADASW::Input texcoord_input( + COLLADASW::InputSemantic::TEXCOORD, + makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)), + 2, // this is only until we have optimized UV sets + (this->export_settings->active_uv_only) ? 0 : layer_index - 1 //set (0,1,2,...) + ); + til.push_back(texcoord_input); + } + } + + int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + if (totlayer_mcol > 0) { + int map_index = 0; + + for (int a = 0; a < totlayer_mcol; a++) { + char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); + COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, + makeUrl(makeVertexColorSourceId(geom_id, layer_name)), + (has_uvs) ? 3 : 2, // all color layers have same index order + map_index // set number equals color map index + ); + til.push_back(input4); + map_index++; + } + } + + // performs the actual writing + prepareToAppendValues(is_triangulated, *primitive_list, vcount_list); + + // <p> + int texindex = 0; + for (int i = 0; i < totpolys; i++) { + MPoly *p = &mpolys[i]; + int loop_count = p->totloop; + + if (p->mat_nr == material_index) { + MLoop *l = &mloops[p->loopstart]; + BCPolygonNormalsIndices normal_indices = norind[i]; + + for (int j = 0; j < loop_count; j++) { + primitive_list->appendValues(l[j].v); + primitive_list->appendValues(normal_indices[j]); + if (has_uvs) + primitive_list->appendValues(texindex + j); + + if (has_color) + primitive_list->appendValues(texindex + j); + } + } + + texindex += loop_count; + } + + finish_and_delete_primitive_List(is_triangulated, primitive_list); } - // creates <source> for positions void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) { #if 0 - int totverts = dm->getNumVerts(dm); - MVert *verts = dm->getVertArray(dm); + int totverts = dm->getNumVerts(dm); + MVert *verts = dm->getVertArray(dm); #endif - int totverts = me->totvert; - MVert *verts = me->mvert; - - COLLADASW::FloatSourceF source(mSW); - source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); - source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION) + - ARRAY_ID_SUFFIX); - source.setAccessorCount(totverts); - source.setAccessorStride(3); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("X"); - param.push_back("Y"); - param.push_back("Z"); - /* main function, it creates <source id = "">, <float_array id = "" - * count = ""> */ - source.prepareToAppendValues(); - //appends data to <float_array> - int i = 0; - for (i = 0; i < totverts; i++) { - source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]); - } - - source.finish(); - + int totverts = me->totvert; + MVert *verts = me->mvert; + + COLLADASW::FloatSourceF source(mSW); + source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); + source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION) + + ARRAY_ID_SUFFIX); + source.setAccessorCount(totverts); + source.setAccessorStride(3); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("X"); + param.push_back("Y"); + param.push_back("Z"); + /* main function, it creates <source id = "">, <float_array id = "" + * count = ""> */ + source.prepareToAppendValues(); + //appends data to <float_array> + int i = 0; + for (i = 0; i < totverts; i++) { + source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]); + } + + source.finish(); } void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) { - /* Find number of vertex color layers */ - int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); - if (totlayer_mcol == 0) - return; - - int map_index = 0; - for (int a = 0; a < totlayer_mcol; a++) { - - map_index++; - MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, a); - - COLLADASW::FloatSourceF source(mSW); - - char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); - std::string layer_id = makeVertexColorSourceId(geom_id, layer_name); - source.setId(layer_id); - - source.setNodeName(layer_name); - - source.setArrayId(layer_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(me->totloop); - source.setAccessorStride(4); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("R"); - param.push_back("G"); - param.push_back("B"); - param.push_back("A"); - - source.prepareToAppendValues(); - - MPoly *mpoly; - int i; - for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) { - MLoopCol *mlc = mloopcol + mpoly->loopstart; - for (int j = 0; j < mpoly->totloop; j++, mlc++) { - source.appendValues( - mlc->r / 255.0f, - mlc->g / 255.0f, - mlc->b / 255.0f, - mlc->a / 255.0f - ); - } - } - - source.finish(); - } -} + /* Find number of vertex color layers */ + int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + if (totlayer_mcol == 0) + return; + + int map_index = 0; + for (int a = 0; a < totlayer_mcol; a++) { + + map_index++; + MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, a); + + COLLADASW::FloatSourceF source(mSW); + + char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); + std::string layer_id = makeVertexColorSourceId(geom_id, layer_name); + source.setId(layer_id); + + source.setNodeName(layer_name); + + source.setArrayId(layer_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(me->totloop); + source.setAccessorStride(4); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("R"); + param.push_back("G"); + param.push_back("B"); + param.push_back("A"); -std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int layer_index, bool is_single_layer) + source.prepareToAppendValues(); + + MPoly *mpoly; + int i; + for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) { + MLoopCol *mlc = mloopcol + mpoly->loopstart; + for (int j = 0; j < mpoly->totloop; j++, mlc++) { + source.appendValues(mlc->r / 255.0f, mlc->g / 255.0f, mlc->b / 255.0f, mlc->a / 255.0f); + } + } + + source.finish(); + } +} + +std::string GeometryExporter::makeTexcoordSourceId(std::string &geom_id, + int layer_index, + bool is_single_layer) { - char suffix[20]; - if (is_single_layer) { - suffix[0] = '\0'; - } - else { - sprintf(suffix, "-%d", layer_index); - } - return getIdBySemantics(geom_id, COLLADASW::InputSemantic::TEXCOORD) + suffix; + char suffix[20]; + if (is_single_layer) { + suffix[0] = '\0'; + } + else { + sprintf(suffix, "-%d", layer_index); + } + return getIdBySemantics(geom_id, COLLADASW::InputSemantic::TEXCOORD) + suffix; } //creates <source> for texcoords void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) { - int totpoly = me->totpoly; - int totuv = me->totloop; - MPoly *mpolys = me->mpoly; - - int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - - // write <source> for each layer - // each <source> will get id like meshName + "map-channel-1" - int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); - for (int a = 0; a < num_layers; a++) { - int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a); - if (!this->export_settings->active_uv_only || layer_index == active_uv_index) { - MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a); - - COLLADASW::FloatSourceF source(mSW); - std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only); - source.setId(layer_id); - source.setArrayId(layer_id + ARRAY_ID_SUFFIX); - - source.setAccessorCount(totuv); - source.setAccessorStride(2); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("S"); - param.push_back("T"); - - source.prepareToAppendValues(); - - for (int index = 0; index < totpoly; index++) { - MPoly *mpoly = mpolys+index; - MLoopUV *mloop = mloops+mpoly->loopstart; - for (int j = 0; j < mpoly->totloop; j++) { - source.appendValues(mloop[j].uv[0], - mloop[j].uv[1]); - } - } - - source.finish(); - } - } + int totpoly = me->totpoly; + int totuv = me->totloop; + MPoly *mpolys = me->mpoly; + + int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); + + // write <source> for each layer + // each <source> will get id like meshName + "map-channel-1" + int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); + for (int a = 0; a < num_layers; a++) { + int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a); + if (!this->export_settings->active_uv_only || layer_index == active_uv_index) { + MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a); + + COLLADASW::FloatSourceF source(mSW); + std::string layer_id = makeTexcoordSourceId( + geom_id, a, this->export_settings->active_uv_only); + source.setId(layer_id); + source.setArrayId(layer_id + ARRAY_ID_SUFFIX); + + source.setAccessorCount(totuv); + source.setAccessorStride(2); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("S"); + param.push_back("T"); + + source.prepareToAppendValues(); + + for (int index = 0; index < totpoly; index++) { + MPoly *mpoly = mpolys + index; + MLoopUV *mloop = mloops + mpoly->loopstart; + for (int j = 0; j < mpoly->totloop; j++) { + source.appendValues(mloop[j].uv[0], mloop[j].uv[1]); + } + } + + source.finish(); + } + } } bool operator<(const Normal &a, const Normal &b) { - /* only needed to sort normal vectors and find() them later in a map.*/ - return a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z))); + /* only needed to sort normal vectors and find() them later in a map.*/ + return a.x < b.x || (a.x == b.x && (a.y < b.y || (a.y == b.y && a.z < b.z))); } //creates <source> for normals -void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor) +void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal> &nor) { #if 0 - int totverts = dm->getNumVerts(dm); - MVert *verts = dm->getVertArray(dm); + int totverts = dm->getNumVerts(dm); + MVert *verts = dm->getVertArray(dm); #endif - COLLADASW::FloatSourceF source(mSW); - source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL)); - source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL) + - ARRAY_ID_SUFFIX); - source.setAccessorCount((unsigned long)nor.size()); - source.setAccessorStride(3); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("X"); - param.push_back("Y"); - param.push_back("Z"); - - source.prepareToAppendValues(); - - std::vector<Normal>::iterator it; - for (it = nor.begin(); it != nor.end(); it++) { - Normal& n = *it; - source.appendValues(n.x, n.y, n.z); - } - - source.finish(); + COLLADASW::FloatSourceF source(mSW); + source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL)); + source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL) + ARRAY_ID_SUFFIX); + source.setAccessorCount((unsigned long)nor.size()); + source.setAccessorStride(3); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("X"); + param.push_back("Y"); + param.push_back("Z"); + + source.prepareToAppendValues(); + + std::vector<Normal>::iterator it; + for (it = nor.begin(); it != nor.end(); it++) { + Normal &n = *it; + source.appendValues(n.x, n.y, n.z); + } + + source.finish(); } -void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me) +void GeometryExporter::create_normals(std::vector<Normal> &normals, + std::vector<BCPolygonNormalsIndices> &polygons_normals, + Mesh *me) { - std::map<Normal, unsigned int> shared_normal_indices; - int last_normal_index = -1; - - MVert *verts = me->mvert; - MLoop *mloops = me->mloop; - float(*lnors)[3] = NULL; - bool use_custom_normals = false; - - BKE_mesh_calc_normals_split(me); - if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { - lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); - use_custom_normals = true; - } - - for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { - MPoly *mpoly = &me->mpoly[poly_index]; - bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH; - - if (!use_vertex_normals) { - // For flat faces use face normal as vertex normal: - - float vector[3]; - BKE_mesh_calc_poly_normal(mpoly, mloops+mpoly->loopstart, verts, vector); - - Normal n = { vector[0], vector[1], vector[2] }; - normals.push_back(n); - last_normal_index++; - } - - BCPolygonNormalsIndices poly_indices; - for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { - unsigned int loop_idx = mpoly->loopstart + loop_index; - if (use_vertex_normals) { - float normalized[3]; - - if (use_custom_normals) { - normalize_v3_v3(normalized, lnors[loop_idx]); - } - else { - normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no); - normalize_v3(normalized); - } - Normal n = { normalized[0], normalized[1], normalized[2] }; - - if (shared_normal_indices.find(n) != shared_normal_indices.end()) { - poly_indices.add_index(shared_normal_indices[n]); - } - else { - last_normal_index++; - poly_indices.add_index(last_normal_index); - shared_normal_indices[n] = last_normal_index; - normals.push_back(n); - } - } - else { - poly_indices.add_index(last_normal_index); - } - } - - polygons_normals.push_back(poly_indices); - } + std::map<Normal, unsigned int> shared_normal_indices; + int last_normal_index = -1; + + MVert *verts = me->mvert; + MLoop *mloops = me->mloop; + float(*lnors)[3] = NULL; + bool use_custom_normals = false; + + BKE_mesh_calc_normals_split(me); + if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { + lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); + use_custom_normals = true; + } + + for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { + MPoly *mpoly = &me->mpoly[poly_index]; + bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH; + + if (!use_vertex_normals) { + // For flat faces use face normal as vertex normal: + + float vector[3]; + BKE_mesh_calc_poly_normal(mpoly, mloops + mpoly->loopstart, verts, vector); + + Normal n = {vector[0], vector[1], vector[2]}; + normals.push_back(n); + last_normal_index++; + } + + BCPolygonNormalsIndices poly_indices; + for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { + unsigned int loop_idx = mpoly->loopstart + loop_index; + if (use_vertex_normals) { + float normalized[3]; + + if (use_custom_normals) { + normalize_v3_v3(normalized, lnors[loop_idx]); + } + else { + normal_short_to_float_v3(normalized, verts[mloops[loop_index].v].no); + normalize_v3(normalized); + } + Normal n = {normalized[0], normalized[1], normalized[2]}; + + if (shared_normal_indices.find(n) != shared_normal_indices.end()) { + poly_indices.add_index(shared_normal_indices[n]); + } + else { + last_normal_index++; + poly_indices.add_index(last_normal_index); + shared_normal_indices[n] = last_normal_index; + normals.push_back(n); + } + } + else { + poly_indices.add_index(last_normal_index); + } + } + + polygons_normals.push_back(poly_indices); + } } -std::string GeometryExporter::getIdBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix) +std::string GeometryExporter::getIdBySemantics(std::string geom_id, + COLLADASW::InputSemantic::Semantics type, + std::string other_suffix) { - return geom_id + getSuffixBySemantic(type) + other_suffix; + return geom_id + getSuffixBySemantic(type) + other_suffix; } - -COLLADASW::URI GeometryExporter::getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix) +COLLADASW::URI GeometryExporter::getUrlBySemantics(std::string geom_id, + COLLADASW::InputSemantic::Semantics type, + std::string other_suffix) { - std::string id(getIdBySemantics(geom_id, type, other_suffix)); - return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id); - + std::string id(getIdBySemantics(geom_id, type, other_suffix)); + return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id); } COLLADASW::URI GeometryExporter::makeUrl(std::string id) { - return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id); + return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id); } diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 5eba68165d2..1e2643b7e57 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -43,103 +43,104 @@ struct Depsgraph; extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob); -class Normal -{ - public: - float x; - float y; - float z; - - friend bool operator< (const Normal &, const Normal &); +class Normal { + public: + float x; + float y; + float z; + friend bool operator<(const Normal &, const Normal &); }; -bool operator< (const Normal &, const Normal &); - +bool operator<(const Normal &, const Normal &); // TODO: optimize UV sets by making indexed list with duplicates removed -class GeometryExporter : COLLADASW::LibraryGeometries -{ - struct Face - { - unsigned int v1, v2, v3, v4; - }; - - Normal n; +class GeometryExporter : COLLADASW::LibraryGeometries { + struct Face { + unsigned int v1, v2, v3, v4; + }; -public: + Normal n; - // TODO: optimize UV sets by making indexed list with duplicates removed - GeometryExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : - COLLADASW::LibraryGeometries(sw), - blender_context(blender_context), - export_settings(export_settings) - {} + public: + // TODO: optimize UV sets by making indexed list with duplicates removed + GeometryExporter(BlenderContext &blender_context, + COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings) + : COLLADASW::LibraryGeometries(sw), + blender_context(blender_context), + export_settings(export_settings) + { + } - void exportGeom(); + void exportGeom(); - void operator()(Object *ob); + void operator()(Object *ob); - void createLooseEdgeList(Object *ob, - Mesh *me, - std::string& geom_id); + void createLooseEdgeList(Object *ob, Mesh *me, std::string &geom_id); - // powerful because it handles both cases when there is material and when there's not - void create_mesh_primitive_list(short material_index, - bool has_uvs, - bool has_color, - Object *ob, - Mesh *me, - std::string& geom_id, - std::vector<BCPolygonNormalsIndices>& norind); + // powerful because it handles both cases when there is material and when there's not + void create_mesh_primitive_list(short material_index, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string &geom_id, + std::vector<BCPolygonNormalsIndices> &norind); - // creates <source> for positions - void createVertsSource(std::string geom_id, Mesh *me); + // creates <source> for positions + void createVertsSource(std::string geom_id, Mesh *me); - void createVertexColorSource(std::string geom_id, Mesh *me); + void createVertexColorSource(std::string geom_id, Mesh *me); - std::string makeTexcoordSourceId(std::string& geom_id, int layer_index, bool is_single_layer); + std::string makeTexcoordSourceId(std::string &geom_id, int layer_index, bool is_single_layer); - //creates <source> for texcoords - void createTexcoordsSource(std::string geom_id, Mesh *me); - void createTesselatedTexcoordsSource(std::string geom_id, Mesh *me); + //creates <source> for texcoords + void createTexcoordsSource(std::string geom_id, Mesh *me); + void createTesselatedTexcoordsSource(std::string geom_id, Mesh *me); - //creates <source> for normals - void createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor); + //creates <source> for normals + void createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal> &nor); - void create_normals(std::vector<Normal> &nor, std::vector<BCPolygonNormalsIndices> &ind, Mesh *me); + void create_normals(std::vector<Normal> &nor, + std::vector<BCPolygonNormalsIndices> &ind, + Mesh *me); - std::string getIdBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = ""); - std::string makeVertexColorSourceId(std::string& geom_id, char *layer_name); + std::string getIdBySemantics(std::string geom_id, + COLLADASW::InputSemantic::Semantics type, + std::string other_suffix = ""); + std::string makeVertexColorSourceId(std::string &geom_id, char *layer_name); - COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = ""); + COLLADASW::URI getUrlBySemantics(std::string geom_id, + COLLADASW::InputSemantic::Semantics type, + std::string other_suffix = ""); - COLLADASW::URI makeUrl(std::string id); + COLLADASW::URI makeUrl(std::string id); - void export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb); + void export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb); -private: - std::set<std::string> exportedGeometry; - BlenderContext &blender_context; - const ExportSettings *export_settings; + private: + std::set<std::string> exportedGeometry; + BlenderContext &blender_context; + const ExportSettings *export_settings; - Mesh *get_mesh(Scene *sce, Object *ob, int apply_modifiers); + Mesh *get_mesh(Scene *sce, Object *ob, int apply_modifiers); }; struct GeometryFunctor { - // f should have - // void operator()(Object *ob) - template<class Functor> - void forEachMeshObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) - { - LinkNode *node; - for (node=export_set; node; node = node->next) { - Object *ob = (Object *)node->link; - if (ob->type == OB_MESH) { - f(ob); - } - } - } + // f should have + // void operator()(Object *ob) + template<class Functor> + void forEachMeshObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) + { + LinkNode *node; + for (node = export_set; node; node = node->next) { + Object *ob = (Object *)node->link; + if (ob->type == OB_MESH) { + f(ob); + } + } + } }; #endif diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index a36abc6165d..1a5c42aee52 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - #include "COLLADABUURI.h" #include "COLLADASWImage.h" @@ -43,123 +42,127 @@ extern "C" { #include "ImageExporter.h" #include "MaterialExporter.h" - -ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map) : - COLLADASW::LibraryImages(sw), - export_settings(export_settings), - key_image_map(key_image_map) +ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings, + KeyImageMap &key_image_map) + : COLLADASW::LibraryImages(sw), export_settings(export_settings), key_image_map(key_image_map) { - /* pass */ + /* pass */ } void ImagesExporter::export_UV_Image(Image *image, bool use_copies) { - std::string name(id_name(image)); - std::string translated_name(translate_id(name)); - - ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL); - if (!imbuf) { - fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); - return; - } + std::string name(id_name(image)); + std::string translated_name(translate_id(name)); - bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0; + ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL); + if (!imbuf) { + fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); + return; + } - ImageFormatData imageFormat; - BKE_imbuf_to_image_format(&imageFormat, imbuf); + bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0; - short image_source = image->source; - bool is_generated = image_source == IMA_SRC_GENERATED; - bool is_packed = BKE_image_has_packedfile(image); + ImageFormatData imageFormat; + BKE_imbuf_to_image_format(&imageFormat, imbuf); - char export_path[FILE_MAX]; - char source_path[FILE_MAX]; - char export_dir[FILE_MAX]; - char export_file[FILE_MAX]; + short image_source = image->source; + bool is_generated = image_source == IMA_SRC_GENERATED; + bool is_packed = BKE_image_has_packedfile(image); - // Destination folder for exported assets - BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir)); + char export_path[FILE_MAX]; + char source_path[FILE_MAX]; + char export_dir[FILE_MAX]; + char export_file[FILE_MAX]; - if (is_generated || is_dirty || use_copies || is_packed) { + // Destination folder for exported assets + BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir)); - // make absolute destination path + if (is_generated || is_dirty || use_copies || is_packed) { - BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); - BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); + // make absolute destination path - BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file); + BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); + BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); - // make dest directory if it doesn't exist - BLI_make_existing_file(export_path); - } + BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file); - if (is_generated || is_dirty || is_packed) { + // make dest directory if it doesn't exist + BLI_make_existing_file(export_path); + } - // This image in its current state only exists in Blender memory. - // So we have to export it. The export will keep the image state intact, - // so the exported file will not be associated with the image. + if (is_generated || is_dirty || is_packed) { - if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) { - fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path); - return; - } - BLI_strncpy(export_path, export_file, sizeof(export_path)); - } - else { + // This image in its current state only exists in Blender memory. + // So we have to export it. The export will keep the image state intact, + // so the exported file will not be associated with the image. - // make absolute source path - BLI_strncpy(source_path, image->name, sizeof(source_path)); - BLI_path_abs(source_path, BKE_main_blendfile_path_from_global()); - BLI_cleanup_path(NULL, source_path); + if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) { + fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path); + return; + } + BLI_strncpy(export_path, export_file, sizeof(export_path)); + } + else { - if (use_copies) { + // make absolute source path + BLI_strncpy(source_path, image->name, sizeof(source_path)); + BLI_path_abs(source_path, BKE_main_blendfile_path_from_global()); + BLI_cleanup_path(NULL, source_path); - // This image is already located on the file system. - // But we want to create copies here. - // To move images into the same export directory. - // Note: If an image is already located in the export folder, - // then skip the copy (as it would result in a file copy error). + if (use_copies) { - if (BLI_path_cmp(source_path, export_path) != 0) { - if (BLI_copy(source_path, export_path) != 0) { - fprintf(stderr, "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", source_path, export_path); - return; - } - } + // This image is already located on the file system. + // But we want to create copies here. + // To move images into the same export directory. + // Note: If an image is already located in the export folder, + // then skip the copy (as it would result in a file copy error). - BLI_strncpy(export_path, export_file, sizeof(export_path)); + if (BLI_path_cmp(source_path, export_path) != 0) { + if (BLI_copy(source_path, export_path) != 0) { + fprintf(stderr, + "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", + source_path, + export_path); + return; + } + } - } - else { + BLI_strncpy(export_path, export_file, sizeof(export_path)); + } + else { - // Do not make any copies, but use the source path directly as reference - // to the original image + // Do not make any copies, but use the source path directly as reference + // to the original image - BLI_strncpy(export_path, source_path, sizeof(export_path)); - } - } + BLI_strncpy(export_path, source_path, sizeof(export_path)); + } + } - COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ - img.add(mSW); - fprintf(stdout, "Collada export: Added image: %s\n", export_file); + COLLADASW::Image img( + COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), + translated_name, + translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ + img.add(mSW); + fprintf(stdout, "Collada export: Added image: %s\n", export_file); - BKE_image_release_ibuf(image, imbuf, NULL); + BKE_image_release_ibuf(image, imbuf, NULL); } void ImagesExporter::exportImages(Scene *sce) { - bool use_texture_copies = this->export_settings->use_texture_copies; - openLibrary(); + bool use_texture_copies = this->export_settings->use_texture_copies; + openLibrary(); - KeyImageMap::iterator iter; - for (iter = key_image_map.begin(); iter != key_image_map.end(); iter++) { + KeyImageMap::iterator iter; + for (iter = key_image_map.begin(); iter != key_image_map.end(); iter++) { - Image *image = iter->second; - std::string uid(id_name(image)); - std::string key = translate_id(uid); + Image *image = iter->second; + std::string uid(id_name(image)); + std::string key = translate_id(uid); - export_UV_Image(image, use_texture_copies); - } + export_UV_Image(image, use_texture_copies); + } - closeLibrary(); + closeLibrary(); } diff --git a/source/blender/collada/ImageExporter.h b/source/blender/collada/ImageExporter.h index 7c1046f7943..ac0c1d5c976 100644 --- a/source/blender/collada/ImageExporter.h +++ b/source/blender/collada/ImageExporter.h @@ -35,17 +35,17 @@ #include "ExportSettings.h" #include "collada_utils.h" -class ImagesExporter: COLLADASW::LibraryImages -{ -public: - ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings, KeyImageMap &key_image_map); - void exportImages(Scene *sce); - -private: - const ExportSettings *export_settings; - KeyImageMap &key_image_map; - void export_UV_Image(Image *image, bool use_texture_copies); - +class ImagesExporter : COLLADASW::LibraryImages { + public: + ImagesExporter(COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings, + KeyImageMap &key_image_map); + void exportImages(Scene *sce); + + private: + const ExportSettings *export_settings; + KeyImageMap &key_image_map; + void export_UV_Image(Image *image, bool use_texture_copies); }; #endif diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h index b8272cf747f..608d8bff882 100644 --- a/source/blender/collada/ImportSettings.h +++ b/source/blender/collada/ImportSettings.h @@ -22,13 +22,13 @@ #define __IMPORTSETTINGS_H__ typedef struct ImportSettings { - bool import_units; - bool find_chains; - bool auto_connect; - bool fix_orientation; - int min_chain_length; - char *filepath; - bool keep_bind_info; + bool import_units; + bool find_chains; + bool auto_connect; + bool fix_orientation; + int min_chain_length; + char *filepath; + bool keep_bind_info; } ImportSettings; #endif diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp index 819f5244ba0..5c4f574c1b7 100644 --- a/source/blender/collada/InstanceWriter.cpp +++ b/source/blender/collada/InstanceWriter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - #include <string> #include <sstream> @@ -34,35 +33,38 @@ extern "C" { #include "collada_internal.h" #include "collada_utils.h" -void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only) +void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial &bind_material, + Object *ob, + bool active_uv_only) { - for (int a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); + for (int a = 0; a < ob->totcol; a++) { + Material *ma = give_current_material(ob, a + 1); - COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList(); + COLLADASW::InstanceMaterialList &iml = bind_material.getInstanceMaterialList(); - if (ma) { - std::string matid(get_material_id(ma)); - matid = translate_id(matid); - std::ostringstream ostr; - ostr << matid; - COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid)); + if (ma) { + std::string matid(get_material_id(ma)); + matid = translate_id(matid); + std::ostringstream ostr; + ostr << matid; + COLLADASW::InstanceMaterial im(ostr.str(), + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid)); - // create <bind_vertex_input> for each uv map - Mesh *me = (Mesh *)ob->data; + // create <bind_vertex_input> for each uv map + Mesh *me = (Mesh *)ob->data; - int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); + int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - int map_index = 0; - int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); - for (int b = 0; b < num_layers; b++) { - if (!active_uv_only || b == active_uv_index) { - char *name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, b); - im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++)); - } - } + int map_index = 0; + int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); + for (int b = 0; b < num_layers; b++) { + if (!active_uv_only || b == active_uv_index) { + char *name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, b); + im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++)); + } + } - iml.push_back(im); - } - } + iml.push_back(im); + } + } } diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h index ea5e9fd58fe..cfec1cf7006 100644 --- a/source/blender/collada/InstanceWriter.h +++ b/source/blender/collada/InstanceWriter.h @@ -25,10 +25,11 @@ #include "DNA_object_types.h" -class InstanceWriter -{ -protected: - void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only); +class InstanceWriter { + protected: + void add_material_bindings(COLLADASW::BindMaterial &bind_material, + Object *ob, + bool active_uv_only); }; #endif diff --git a/source/blender/collada/LightExporter.cpp b/source/blender/collada/LightExporter.cpp index c1822a8e5f3..39721b2eb3c 100644 --- a/source/blender/collada/LightExporter.cpp +++ b/source/blender/collada/LightExporter.cpp @@ -31,125 +31,126 @@ template<class Functor> void forEachLightObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { - LinkNode *node; - for (node = export_set; node; node = node->next) { - Object *ob = (Object *)node->link; - - if (ob->type == OB_LAMP && ob->data) { - f(ob); - } - } + LinkNode *node; + for (node = export_set; node; node = node->next) { + Object *ob = (Object *)node->link; + + if (ob->type == OB_LAMP && ob->data) { + f(ob); + } + } } -LightsExporter::LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryLights(sw), export_settings(export_settings) { +LightsExporter::LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) + : COLLADASW::LibraryLights(sw), export_settings(export_settings) +{ } void LightsExporter::exportLights(Scene *sce) { - openLibrary(); + openLibrary(); - forEachLightObjectInExportSet(sce, *this, this->export_settings->export_set); + forEachLightObjectInExportSet(sce, *this, this->export_settings->export_set); - closeLibrary(); + closeLibrary(); } void LightsExporter::operator()(Object *ob) { - Light *la = (Light *)ob->data; - std::string la_id(get_light_id(ob)); - std::string la_name(id_name(la)); - COLLADASW::Color col(la->r * la->energy, la->g * la->energy, la->b * la->energy); - float d, constatt, linatt, quadatt; - - d = la->dist; - - constatt = 1.0f; - - if (la->falloff_type == LA_FALLOFF_INVLINEAR) { - linatt = 1.0f / d; - quadatt = 0.0f; - } - else { - linatt = 0.0f; - quadatt = 1.0f / (d * d); - } - - // sun - if (la->type == LA_SUN) { - COLLADASW::DirectionalLight cla(mSW, la_id, la_name); - cla.setColor(col, false, "color"); - cla.setConstantAttenuation(constatt); - exportBlenderProfile(cla, la); - addLight(cla); - } - - // spot - else if (la->type == LA_SPOT) { - COLLADASW::SpotLight cla(mSW, la_id, la_name); - cla.setColor(col, false, "color"); - cla.setFallOffAngle(RAD2DEGF(la->spotsize), false, "fall_off_angle"); - cla.setFallOffExponent(la->spotblend, false, "fall_off_exponent"); - cla.setConstantAttenuation(constatt); - cla.setLinearAttenuation(linatt); - cla.setQuadraticAttenuation(quadatt); - exportBlenderProfile(cla, la); - addLight(cla); - } - // lamp - else if (la->type == LA_LOCAL) { - COLLADASW::PointLight cla(mSW, la_id, la_name); - cla.setColor(col, false, "color"); - cla.setConstantAttenuation(constatt); - cla.setLinearAttenuation(linatt); - cla.setQuadraticAttenuation(quadatt); - exportBlenderProfile(cla, la); - addLight(cla); - } - // area light is not supported - // it will be exported as a local lamp - else { - COLLADASW::PointLight cla(mSW, la_id, la_name); - cla.setColor(col, false, "color"); - cla.setConstantAttenuation(constatt); - cla.setLinearAttenuation(linatt); - cla.setQuadraticAttenuation(quadatt); - exportBlenderProfile(cla, la); - addLight(cla); - } - + Light *la = (Light *)ob->data; + std::string la_id(get_light_id(ob)); + std::string la_name(id_name(la)); + COLLADASW::Color col(la->r * la->energy, la->g * la->energy, la->b * la->energy); + float d, constatt, linatt, quadatt; + + d = la->dist; + + constatt = 1.0f; + + if (la->falloff_type == LA_FALLOFF_INVLINEAR) { + linatt = 1.0f / d; + quadatt = 0.0f; + } + else { + linatt = 0.0f; + quadatt = 1.0f / (d * d); + } + + // sun + if (la->type == LA_SUN) { + COLLADASW::DirectionalLight cla(mSW, la_id, la_name); + cla.setColor(col, false, "color"); + cla.setConstantAttenuation(constatt); + exportBlenderProfile(cla, la); + addLight(cla); + } + + // spot + else if (la->type == LA_SPOT) { + COLLADASW::SpotLight cla(mSW, la_id, la_name); + cla.setColor(col, false, "color"); + cla.setFallOffAngle(RAD2DEGF(la->spotsize), false, "fall_off_angle"); + cla.setFallOffExponent(la->spotblend, false, "fall_off_exponent"); + cla.setConstantAttenuation(constatt); + cla.setLinearAttenuation(linatt); + cla.setQuadraticAttenuation(quadatt); + exportBlenderProfile(cla, la); + addLight(cla); + } + // lamp + else if (la->type == LA_LOCAL) { + COLLADASW::PointLight cla(mSW, la_id, la_name); + cla.setColor(col, false, "color"); + cla.setConstantAttenuation(constatt); + cla.setLinearAttenuation(linatt); + cla.setQuadraticAttenuation(quadatt); + exportBlenderProfile(cla, la); + addLight(cla); + } + // area light is not supported + // it will be exported as a local lamp + else { + COLLADASW::PointLight cla(mSW, la_id, la_name); + cla.setColor(col, false, "color"); + cla.setConstantAttenuation(constatt); + cla.setLinearAttenuation(linatt); + cla.setQuadraticAttenuation(quadatt); + exportBlenderProfile(cla, la); + addLight(cla); + } } bool LightsExporter::exportBlenderProfile(COLLADASW::Light &cla, Light *la) { - cla.addExtraTechniqueParameter("blender", "type", la->type); - cla.addExtraTechniqueParameter("blender", "flag", la->flag); - cla.addExtraTechniqueParameter("blender", "mode", la->mode); - cla.addExtraTechniqueParameter("blender", "gamma", la->k, "blender_gamma"); - cla.addExtraTechniqueParameter("blender", "red", la->r); - cla.addExtraTechniqueParameter("blender", "green", la->g); - cla.addExtraTechniqueParameter("blender", "blue", la->b); - cla.addExtraTechniqueParameter("blender", "shadow_r", la->shdwr, "blender_shadow_r"); - cla.addExtraTechniqueParameter("blender", "shadow_g", la->shdwg, "blender_shadow_g"); - cla.addExtraTechniqueParameter("blender", "shadow_b", la->shdwb, "blender_shadow_b"); - cla.addExtraTechniqueParameter("blender", "energy", la->energy, "blender_energy"); - cla.addExtraTechniqueParameter("blender", "dist", la->dist, "blender_dist"); - cla.addExtraTechniqueParameter("blender", "spotsize", RAD2DEGF(la->spotsize)); - cla.addExtraTechniqueParameter("blender", "spotblend", la->spotblend); - cla.addExtraTechniqueParameter("blender", "att1", la->att1); - cla.addExtraTechniqueParameter("blender", "att2", la->att2); - // \todo figure out how we can have falloff curve supported here - cla.addExtraTechniqueParameter("blender", "falloff_type", la->falloff_type); - cla.addExtraTechniqueParameter("blender", "clipsta", la->clipsta); - cla.addExtraTechniqueParameter("blender", "clipend", la->clipend); - cla.addExtraTechniqueParameter("blender", "bias", la->bias); - cla.addExtraTechniqueParameter("blender", "soft", la->soft); - cla.addExtraTechniqueParameter("blender", "bufsize", la->bufsize); - cla.addExtraTechniqueParameter("blender", "samp", la->samp); - cla.addExtraTechniqueParameter("blender", "buffers", la->buffers); - cla.addExtraTechniqueParameter("blender", "area_shape", la->area_shape); - cla.addExtraTechniqueParameter("blender", "area_size", la->area_size); - cla.addExtraTechniqueParameter("blender", "area_sizey", la->area_sizey); - cla.addExtraTechniqueParameter("blender", "area_sizez", la->area_sizez); - - return true; + cla.addExtraTechniqueParameter("blender", "type", la->type); + cla.addExtraTechniqueParameter("blender", "flag", la->flag); + cla.addExtraTechniqueParameter("blender", "mode", la->mode); + cla.addExtraTechniqueParameter("blender", "gamma", la->k, "blender_gamma"); + cla.addExtraTechniqueParameter("blender", "red", la->r); + cla.addExtraTechniqueParameter("blender", "green", la->g); + cla.addExtraTechniqueParameter("blender", "blue", la->b); + cla.addExtraTechniqueParameter("blender", "shadow_r", la->shdwr, "blender_shadow_r"); + cla.addExtraTechniqueParameter("blender", "shadow_g", la->shdwg, "blender_shadow_g"); + cla.addExtraTechniqueParameter("blender", "shadow_b", la->shdwb, "blender_shadow_b"); + cla.addExtraTechniqueParameter("blender", "energy", la->energy, "blender_energy"); + cla.addExtraTechniqueParameter("blender", "dist", la->dist, "blender_dist"); + cla.addExtraTechniqueParameter("blender", "spotsize", RAD2DEGF(la->spotsize)); + cla.addExtraTechniqueParameter("blender", "spotblend", la->spotblend); + cla.addExtraTechniqueParameter("blender", "att1", la->att1); + cla.addExtraTechniqueParameter("blender", "att2", la->att2); + // \todo figure out how we can have falloff curve supported here + cla.addExtraTechniqueParameter("blender", "falloff_type", la->falloff_type); + cla.addExtraTechniqueParameter("blender", "clipsta", la->clipsta); + cla.addExtraTechniqueParameter("blender", "clipend", la->clipend); + cla.addExtraTechniqueParameter("blender", "bias", la->bias); + cla.addExtraTechniqueParameter("blender", "soft", la->soft); + cla.addExtraTechniqueParameter("blender", "bufsize", la->bufsize); + cla.addExtraTechniqueParameter("blender", "samp", la->samp); + cla.addExtraTechniqueParameter("blender", "buffers", la->buffers); + cla.addExtraTechniqueParameter("blender", "area_shape", la->area_shape); + cla.addExtraTechniqueParameter("blender", "area_size", la->area_size); + cla.addExtraTechniqueParameter("blender", "area_sizey", la->area_sizey); + cla.addExtraTechniqueParameter("blender", "area_sizez", la->area_sizez); + + return true; } diff --git a/source/blender/collada/LightExporter.h b/source/blender/collada/LightExporter.h index 7cd0d2979e5..fc468f1f4a3 100644 --- a/source/blender/collada/LightExporter.h +++ b/source/blender/collada/LightExporter.h @@ -30,15 +30,15 @@ #include "ExportSettings.h" -class LightsExporter: COLLADASW::LibraryLights -{ -public: - LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); - void exportLights(Scene *sce); - void operator()(Object *ob); -private: - bool exportBlenderProfile(COLLADASW::Light &cla, Light *la); - const ExportSettings *export_settings; +class LightsExporter : COLLADASW::LibraryLights { + public: + LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); + void exportLights(Scene *sce); + void operator()(Object *ob); + + private: + bool exportBlenderProfile(COLLADASW::Light &cla, Light *la); + const ExportSettings *export_settings; }; #endif diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp index 0c2a7a09b21..e071712b20d 100644 --- a/source/blender/collada/MaterialExporter.cpp +++ b/source/blender/collada/MaterialExporter.cpp @@ -22,49 +22,53 @@ #include "COLLADABUUtils.h" #include "collada_internal.h" -MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryMaterials(sw), export_settings(export_settings) +MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, + const ExportSettings *export_settings) + : COLLADASW::LibraryMaterials(sw), export_settings(export_settings) { - /* pass */ + /* pass */ } void MaterialsExporter::exportMaterials(Scene *sce) { - if (hasMaterials(sce)) { - openLibrary(); + if (hasMaterials(sce)) { + openLibrary(); - MaterialFunctor mf; - mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set); + MaterialFunctor mf; + mf.forEachMaterialInExportSet<MaterialsExporter>( + sce, *this, this->export_settings->export_set); - closeLibrary(); - } + closeLibrary(); + } } bool MaterialsExporter::hasMaterials(Scene *sce) { - LinkNode *node; - for (node=this->export_settings->export_set; node; node = node->next) { - Object *ob = (Object *)node->link; - int a; - for (a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); + LinkNode *node; + for (node = this->export_settings->export_set; node; node = node->next) { + Object *ob = (Object *)node->link; + int a; + for (a = 0; a < ob->totcol; a++) { + Material *ma = give_current_material(ob, a + 1); - // no material, but check all of the slots - if (!ma) continue; + // no material, but check all of the slots + if (!ma) + continue; - return true; - } - } - return false; + return true; + } + } + return false; } void MaterialsExporter::operator()(Material *ma, Object *ob) { - std::string mat_name = encode_xml(id_name(ma)); - std::string mat_id = get_material_id(ma); - std::string eff_id = get_effect_id(ma); + std::string mat_name = encode_xml(id_name(ma)); + std::string mat_id = get_material_id(ma); + std::string eff_id = get_effect_id(ma); - openMaterial(mat_id, mat_name); - addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, eff_id)); + openMaterial(mat_id, mat_name); + addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, eff_id)); - closeMaterial(); + closeMaterial(); } diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h index debc226c099..d47a001596d 100644 --- a/source/blender/collada/MaterialExporter.h +++ b/source/blender/collada/MaterialExporter.h @@ -28,10 +28,10 @@ #include "COLLADASWStreamWriter.h" extern "C" { - #include "BKE_material.h" - #include "DNA_material_types.h" - #include "DNA_object_types.h" - #include "DNA_scene_types.h" +#include "BKE_material.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" } #include "GeometryExporter.h" @@ -39,58 +39,59 @@ extern "C" { #include "ExportSettings.h" #include "Materials.h" -class MaterialsExporter: COLLADASW::LibraryMaterials -{ -public: - MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); - void exportMaterials(Scene *sce); - void operator()(Material *ma, Object *ob); +class MaterialsExporter : COLLADASW::LibraryMaterials { + public: + MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); + void exportMaterials(Scene *sce); + void operator()(Material *ma, Object *ob); -private: - bool hasMaterials(Scene *sce); - const ExportSettings *export_settings; + private: + bool hasMaterials(Scene *sce); + const ExportSettings *export_settings; }; // used in forEachMaterialInScene -template <class Functor> -class ForEachMaterialFunctor -{ - std::vector<std::string> mMat; // contains list of material names, to avoid duplicate calling of f - Functor *f; -public: - ForEachMaterialFunctor(Functor*f) : f(f) {} - - void operator ()(Object *ob) - { - int a; - for (a = 0; a < ob->totcol; a++) { - - Material *ma = give_current_material(ob, a+1); - - if (!ma) continue; - - std::string translated_id = translate_id(id_name(ma)); - if (find(mMat.begin(), mMat.end(), translated_id) == mMat.end()) { - (*this->f)(ma, ob); - - mMat.push_back(translated_id); - } - } - } +template<class Functor> class ForEachMaterialFunctor { + std::vector<std::string> + mMat; // contains list of material names, to avoid duplicate calling of f + Functor *f; + + public: + ForEachMaterialFunctor(Functor *f) : f(f) + { + } + + void operator()(Object *ob) + { + int a; + for (a = 0; a < ob->totcol; a++) { + + Material *ma = give_current_material(ob, a + 1); + + if (!ma) + continue; + + std::string translated_id = translate_id(id_name(ma)); + if (find(mMat.begin(), mMat.end(), translated_id) == mMat.end()) { + (*this->f)(ma, ob); + + mMat.push_back(translated_id); + } + } + } }; struct MaterialFunctor { - // calls f for each unique material linked to each object in sce - // f should have - // void operator()(Material *ma) - template<class Functor> - void forEachMaterialInExportSet(Scene *sce, Functor &f, LinkNode *export_set) - { - ForEachMaterialFunctor<Functor> matfunc(&f); - GeometryFunctor gf; - gf.forEachMeshObjectInExportSet<ForEachMaterialFunctor<Functor> >(sce, matfunc, export_set); - } + // calls f for each unique material linked to each object in sce + // f should have + // void operator()(Material *ma) + template<class Functor> + void forEachMaterialInExportSet(Scene *sce, Functor &f, LinkNode *export_set) + { + ForEachMaterialFunctor<Functor> matfunc(&f); + GeometryFunctor gf; + gf.forEachMeshObjectInExportSet<ForEachMaterialFunctor<Functor>>(sce, matfunc, export_set); + } }; - #endif diff --git a/source/blender/collada/Materials.cpp b/source/blender/collada/Materials.cpp index d6ed0e2859a..4313e634b23 100644 --- a/source/blender/collada/Materials.cpp +++ b/source/blender/collada/Materials.cpp @@ -16,306 +16,304 @@ #include "Materials.h" -MaterialNode::MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map) : - mContext(C), - material(ma), - effect(nullptr), - key_image_map(&key_image_map) +MaterialNode::MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map) + : mContext(C), material(ma), effect(nullptr), key_image_map(&key_image_map) { - ntree = prepare_material_nodetree(); - setShaderType(); + ntree = prepare_material_nodetree(); + setShaderType(); } -MaterialNode::MaterialNode(bContext *C, COLLADAFW::EffectCommon *ef, Material *ma, UidImageMap &uid_image_map) : - mContext(C), - material(ma), - effect(ef), - uid_image_map(&uid_image_map) +MaterialNode::MaterialNode(bContext *C, + COLLADAFW::EffectCommon *ef, + Material *ma, + UidImageMap &uid_image_map) + : mContext(C), material(ma), effect(ef), uid_image_map(&uid_image_map) { - ntree = prepare_material_nodetree(); - setShaderType(); + ntree = prepare_material_nodetree(); + setShaderType(); - std::map<std::string, bNode *> nmap; + std::map<std::string, bNode *> nmap; #if 0 - nmap["main"] = add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300); - nmap["emission"] = add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission"); - nmap["add"] = add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400); - nmap["transparent"] = add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200); - nmap["mix"] = add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency"); - nmap["out"] = add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300); - nmap["out"]->flag &= ~NODE_SELECT; - - add_link(ntree, nmap["emission"], 0, nmap["add"], 0); - add_link(ntree, nmap["main"], 0, nmap["add"], 1); - add_link(ntree, nmap["add"], 0, nmap["mix"], 1); - add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2); - - add_link(ntree, nmap["mix"], 0, nmap["out"], 0); - // experimental, probably not used. - make_group(C, ntree, nmap); + nmap["main"] = add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300); + nmap["emission"] = add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission"); + nmap["add"] = add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400); + nmap["transparent"] = add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200); + nmap["mix"] = add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency"); + nmap["out"] = add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300); + nmap["out"]->flag &= ~NODE_SELECT; + + add_link(ntree, nmap["emission"], 0, nmap["add"], 0); + add_link(ntree, nmap["main"], 0, nmap["add"], 1); + add_link(ntree, nmap["add"], 0, nmap["mix"], 1); + add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2); + + add_link(ntree, nmap["mix"], 0, nmap["out"], 0); + // experimental, probably not used. + make_group(C, ntree, nmap); #else - shader_node = add_node(SH_NODE_BSDF_PRINCIPLED, 0, 300, ""); - output_node = add_node(SH_NODE_OUTPUT_MATERIAL, 300, 300, ""); - add_link(shader_node, 0, output_node, 0); + shader_node = add_node(SH_NODE_BSDF_PRINCIPLED, 0, 300, ""); + output_node = add_node(SH_NODE_OUTPUT_MATERIAL, 300, 300, ""); + add_link(shader_node, 0, output_node, 0); #endif } void MaterialNode::setShaderType() { #if 0 - COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType(); - // Currently we only support PBR based shaders - // TODO: simulate the effects with PBR - - // blinn - if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) { - ma->spec_shader = MA_SPEC_BLINN; - ma->spec = ef->getShininess().getFloatValue(); - } - // phong - else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) { - ma->spec_shader = MA_SPEC_PHONG; - ma->har = ef->getShininess().getFloatValue(); - } - // lambert - else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) { - ma->diff_shader = MA_DIFF_LAMBERT; - } - // default - lambert - else { - ma->diff_shader = MA_DIFF_LAMBERT; - fprintf(stderr, "Current shader type is not supported, default to lambert.\n"); - } + COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType(); + // Currently we only support PBR based shaders + // TODO: simulate the effects with PBR + + // blinn + if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) { + ma->spec_shader = MA_SPEC_BLINN; + ma->spec = ef->getShininess().getFloatValue(); + } + // phong + else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) { + ma->spec_shader = MA_SPEC_PHONG; + ma->har = ef->getShininess().getFloatValue(); + } + // lambert + else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) { + ma->diff_shader = MA_DIFF_LAMBERT; + } + // default - lambert + else { + ma->diff_shader = MA_DIFF_LAMBERT; + fprintf(stderr, "Current shader type is not supported, default to lambert.\n"); + } #endif } bNodeTree *MaterialNode::prepare_material_nodetree() { - if (material->nodetree == NULL) { - material->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree"); - material->use_nodes = true; - } - return material->nodetree; + if (material->nodetree == NULL) { + material->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree"); + material->use_nodes = true; + } + return material->nodetree; } bNode *MaterialNode::add_node(int node_type, int locx, int locy, std::string label) { - bNode *node = nodeAddStaticNode(mContext, ntree, node_type); - if (node) { - if (label.length() > 0) { - strcpy(node->label, label.c_str()); - } - node->locx = locx; - node->locy = locy; - node->flag |= NODE_SELECT; - } - node_map[label] = node; - return node; + bNode *node = nodeAddStaticNode(mContext, ntree, node_type); + if (node) { + if (label.length() > 0) { + strcpy(node->label, label.c_str()); + } + node->locx = locx; + node->locy = locy; + node->flag |= NODE_SELECT; + } + node_map[label] = node; + return node; } void MaterialNode::add_link(bNode *from_node, int from_index, bNode *to_node, int to_index) { - bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index); - bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index); + bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index); + bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index); - nodeAddLink(ntree, from_node, from_socket, to_node, to_socket); + nodeAddLink(ntree, from_node, from_socket, to_node, to_socket); } void MaterialNode::set_reflectivity(float val) { - material->metallic = val; - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_METALLIC); - *(float *)socket->default_value = val; + material->metallic = val; + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_METALLIC); + *(float *)socket->default_value = val; } void MaterialNode::set_ior(float val) { - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_IOR); - *(float *)socket->default_value = val; + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_IOR); + *(float *)socket->default_value = val; } void MaterialNode::set_diffuse(COLLADAFW::ColorOrTexture &cot, std::string label) { - int locy = -300 * (node_map.size()-2); - if (cot.isColor()) { - COLLADAFW::Color col = cot.getColor(); - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_DIFFUSE); - float *fcol = (float *)socket->default_value; - - fcol[0] = material->r = col.getRed(); - fcol[1] = material->g = col.getGreen(); - fcol[2] = material->b = col.getBlue(); - fcol[3] = material->a = col.getAlpha(); - } - else if (cot.isTexture()) { - bNode *texture_node = add_texture_node(cot, -300, locy, label); - if (texture_node != NULL) { - add_link(texture_node, 0, shader_node, 0); - } - } + int locy = -300 * (node_map.size() - 2); + if (cot.isColor()) { + COLLADAFW::Color col = cot.getColor(); + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_DIFFUSE); + float *fcol = (float *)socket->default_value; + + fcol[0] = material->r = col.getRed(); + fcol[1] = material->g = col.getGreen(); + fcol[2] = material->b = col.getBlue(); + fcol[3] = material->a = col.getAlpha(); + } + else if (cot.isTexture()) { + bNode *texture_node = add_texture_node(cot, -300, locy, label); + if (texture_node != NULL) { + add_link(texture_node, 0, shader_node, 0); + } + } } Image *MaterialNode::get_diffuse_image() { - bNode *shader = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED); - if (shader == nullptr) { - return nullptr; - } - - bNodeSocket *in_socket = (bNodeSocket *)BLI_findlink(&shader->inputs, BC_PBR_DIFFUSE); - if (in_socket == nullptr) { - return nullptr; - } - - bNodeLink *link = in_socket->link; - if (link == nullptr) { - return nullptr; - } - - bNode *texture = link->fromnode; - if (texture == nullptr) { - return nullptr; - } - - if (texture->type != SH_NODE_TEX_IMAGE) { - return nullptr; - } - - Image *image = (Image *)texture->id; - return image; - + bNode *shader = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED); + if (shader == nullptr) { + return nullptr; + } + + bNodeSocket *in_socket = (bNodeSocket *)BLI_findlink(&shader->inputs, BC_PBR_DIFFUSE); + if (in_socket == nullptr) { + return nullptr; + } + + bNodeLink *link = in_socket->link; + if (link == nullptr) { + return nullptr; + } + + bNode *texture = link->fromnode; + if (texture == nullptr) { + return nullptr; + } + + if (texture->type != SH_NODE_TEX_IMAGE) { + return nullptr; + } + + Image *image = (Image *)texture->id; + return image; } static bNodeSocket *set_color(bNode *node, COLLADAFW::Color col) { - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->outputs, 0); - float *fcol = (float *)socket->default_value; - fcol[0] = col.getRed(); - fcol[1] = col.getGreen(); - fcol[2] = col.getBlue(); + bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->outputs, 0); + float *fcol = (float *)socket->default_value; + fcol[0] = col.getRed(); + fcol[1] = col.getGreen(); + fcol[2] = col.getBlue(); - return socket; + return socket; } void MaterialNode::set_ambient(COLLADAFW::ColorOrTexture &cot, std::string label) { - int locy = -300 * (node_map.size() - 2); - if (cot.isColor()) { - COLLADAFW::Color col = cot.getColor(); - bNode *node = add_node(SH_NODE_RGB, -300, locy, label); - set_color(node, col); - // TODO: Connect node - } - // texture - else if (cot.isTexture()) { - add_texture_node(cot, -300, locy, label); - // TODO: Connect node - } + int locy = -300 * (node_map.size() - 2); + if (cot.isColor()) { + COLLADAFW::Color col = cot.getColor(); + bNode *node = add_node(SH_NODE_RGB, -300, locy, label); + set_color(node, col); + // TODO: Connect node + } + // texture + else if (cot.isTexture()) { + add_texture_node(cot, -300, locy, label); + // TODO: Connect node + } } void MaterialNode::set_reflective(COLLADAFW::ColorOrTexture &cot, std::string label) { - int locy = -300 * (node_map.size() - 2); - if (cot.isColor()) { - COLLADAFW::Color col = cot.getColor(); - bNode *node = add_node(SH_NODE_RGB, -300, locy, label); - set_color(node, col); - // TODO: Connect node - } - // texture - else if (cot.isTexture()) { - add_texture_node(cot, -300, locy, label); - // TODO: Connect node - } + int locy = -300 * (node_map.size() - 2); + if (cot.isColor()) { + COLLADAFW::Color col = cot.getColor(); + bNode *node = add_node(SH_NODE_RGB, -300, locy, label); + set_color(node, col); + // TODO: Connect node + } + // texture + else if (cot.isTexture()) { + add_texture_node(cot, -300, locy, label); + // TODO: Connect node + } } void MaterialNode::set_emission(COLLADAFW::ColorOrTexture &cot, std::string label) { - int locy = -300 * (node_map.size() - 2); - if (cot.isColor()) { - COLLADAFW::Color col = cot.getColor(); - bNode *node = add_node(SH_NODE_RGB, -300, locy, label); - set_color(node, col); - // TODO: Connect node - } - // texture - else if (cot.isTexture()) { - add_texture_node(cot, -300, locy, label); - // TODO: Connect node - } + int locy = -300 * (node_map.size() - 2); + if (cot.isColor()) { + COLLADAFW::Color col = cot.getColor(); + bNode *node = add_node(SH_NODE_RGB, -300, locy, label); + set_color(node, col); + // TODO: Connect node + } + // texture + else if (cot.isTexture()) { + add_texture_node(cot, -300, locy, label); + // TODO: Connect node + } } void MaterialNode::set_opacity(COLLADAFW::ColorOrTexture &cot, std::string label) { - if (effect == nullptr) { - return; - } - - int locy = -300 * (node_map.size() - 2); - if (cot.isColor()) { - COLLADAFW::Color col = effect->getTransparent().getColor(); - float alpha = effect->getTransparency().getFloatValue(); - - if (col.isValid()) { - alpha *= col.getAlpha(); // Assuming A_ONE opaque mode - } - if (col.isValid() || alpha < 1.0) { - // not sure what to do here - } - - bNode *node = add_node(SH_NODE_RGB, -300, locy, label); - set_color(node, col); - // TODO: Connect node - } - // texture - else if (cot.isTexture()) { - add_texture_node(cot, -300, locy, label); - // TODO: Connect node - } + if (effect == nullptr) { + return; + } + + int locy = -300 * (node_map.size() - 2); + if (cot.isColor()) { + COLLADAFW::Color col = effect->getTransparent().getColor(); + float alpha = effect->getTransparency().getFloatValue(); + + if (col.isValid()) { + alpha *= col.getAlpha(); // Assuming A_ONE opaque mode + } + if (col.isValid() || alpha < 1.0) { + // not sure what to do here + } + + bNode *node = add_node(SH_NODE_RGB, -300, locy, label); + set_color(node, col); + // TODO: Connect node + } + // texture + else if (cot.isTexture()) { + add_texture_node(cot, -300, locy, label); + // TODO: Connect node + } } void MaterialNode::set_specular(COLLADAFW::ColorOrTexture &cot, std::string label) { - int locy = -300 * (node_map.size() - 2); - if (cot.isColor()) { - COLLADAFW::Color col = cot.getColor(); - material->specr = col.getRed(); - material->specg = col.getGreen(); - material->specb = col.getBlue(); - - bNode *node = add_node(SH_NODE_RGB, -300, locy, label); - set_color(node, col); - // TODO: Connect node - } - // texture - else if (cot.isTexture()) { - add_texture_node(cot, -300, locy, label); - // TODO: Connect node - } + int locy = -300 * (node_map.size() - 2); + if (cot.isColor()) { + COLLADAFW::Color col = cot.getColor(); + material->specr = col.getRed(); + material->specg = col.getGreen(); + material->specb = col.getBlue(); + + bNode *node = add_node(SH_NODE_RGB, -300, locy, label); + set_color(node, col); + // TODO: Connect node + } + // texture + else if (cot.isTexture()) { + add_texture_node(cot, -300, locy, label); + // TODO: Connect node + } } -bNode *MaterialNode::add_texture_node(COLLADAFW::ColorOrTexture &cot, int locx, int locy, std::string label) +bNode *MaterialNode::add_texture_node(COLLADAFW::ColorOrTexture &cot, + int locx, + int locy, + std::string label) { - if (effect == nullptr) { - return nullptr; - } - - UidImageMap &image_map = *uid_image_map; + if (effect == nullptr) { + return nullptr; + } - COLLADAFW::Texture ctex = cot.getTexture(); + UidImageMap &image_map = *uid_image_map; - COLLADAFW::SamplerPointerArray& samp_array = effect->getSamplerPointerArray(); - COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()]; + COLLADAFW::Texture ctex = cot.getTexture(); - const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage(); + COLLADAFW::SamplerPointerArray &samp_array = effect->getSamplerPointerArray(); + COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()]; - if (image_map.find(ima_uid) == image_map.end()) { - fprintf(stderr, "Couldn't find an image by UID.\n"); - return NULL; - } + const COLLADAFW::UniqueId &ima_uid = sampler->getSourceImage(); - Image *ima = image_map[ima_uid]; - bNode *texture_node = add_node(SH_NODE_TEX_IMAGE, locx, locy, label); - texture_node->id = &ima->id; - return texture_node; + if (image_map.find(ima_uid) == image_map.end()) { + fprintf(stderr, "Couldn't find an image by UID.\n"); + return NULL; + } + Image *ima = image_map[ima_uid]; + bNode *texture_node = add_node(SH_NODE_TEX_IMAGE, locx, locy, label); + texture_node->id = &ima->id; + return texture_node; } diff --git a/source/blender/collada/Materials.h b/source/blender/collada/Materials.h index 3e6dcf896a7..445b9fd0758 100644 --- a/source/blender/collada/Materials.h +++ b/source/blender/collada/Materials.h @@ -32,47 +32,46 @@ extern "C" { #include "COLLADAFWEffectCommon.h" typedef enum BC_pbr_inputs { - BC_PBR_DIFFUSE = 0, - BC_PBR_METALLIC = 4, - BC_PBR_IOR = 14, + BC_PBR_DIFFUSE = 0, + BC_PBR_METALLIC = 4, + BC_PBR_IOR = 14, } BC_pbr_inputs; typedef std::map<std::string, bNode *> NodeMap; class MaterialNode { -private: - bContext *mContext; - Material *material; - COLLADAFW::EffectCommon *effect; - UidImageMap *uid_image_map = nullptr; - KeyImageMap *key_image_map = nullptr; + private: + bContext *mContext; + Material *material; + COLLADAFW::EffectCommon *effect; + UidImageMap *uid_image_map = nullptr; + KeyImageMap *key_image_map = nullptr; - NodeMap node_map; - bNodeTree *ntree; + NodeMap node_map; + bNodeTree *ntree; - bNode *shader_node; - bNode *output_node; + bNode *shader_node; + bNode *output_node; - bNodeTree *prepare_material_nodetree(); - bNode *add_node(int node_type, int locx, int locy, std::string label); - void add_link(bNode *from_node, int from_index, bNode *to_node, int to_index); - bNode *add_texture_node(COLLADAFW::ColorOrTexture &cot, int locx, int locy, std::string label); - void setShaderType(); - -public: - MaterialNode(bContext *C, COLLADAFW::EffectCommon *ef, Material *ma, UidImageMap &uid_image_map); - MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map); - void set_diffuse(COLLADAFW::ColorOrTexture &cot, std::string label); - Image *get_diffuse_image(); - void set_specular(COLLADAFW::ColorOrTexture &cot, std::string label); - void set_ambient(COLLADAFW::ColorOrTexture &cot, std::string label); - void set_reflective(COLLADAFW::ColorOrTexture &cot, std::string label); - void set_emission(COLLADAFW::ColorOrTexture &cot, std::string label); - void set_opacity(COLLADAFW::ColorOrTexture &cot, std::string label); - void set_reflectivity(float val); - void set_ior(float val); + bNodeTree *prepare_material_nodetree(); + bNode *add_node(int node_type, int locx, int locy, std::string label); + void add_link(bNode *from_node, int from_index, bNode *to_node, int to_index); + bNode *add_texture_node(COLLADAFW::ColorOrTexture &cot, int locx, int locy, std::string label); + void setShaderType(); + public: + MaterialNode(bContext *C, COLLADAFW::EffectCommon *ef, Material *ma, UidImageMap &uid_image_map); + MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map); + void set_diffuse(COLLADAFW::ColorOrTexture &cot, std::string label); + Image *get_diffuse_image(); + void set_specular(COLLADAFW::ColorOrTexture &cot, std::string label); + void set_ambient(COLLADAFW::ColorOrTexture &cot, std::string label); + void set_reflective(COLLADAFW::ColorOrTexture &cot, std::string label); + void set_emission(COLLADAFW::ColorOrTexture &cot, std::string label); + void set_opacity(COLLADAFW::ColorOrTexture &cot, std::string label); + void set_reflectivity(float val); + void set_ior(float val); }; #endif diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 07cf7448a75..0c87b139c0c 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -18,11 +18,10 @@ * \ingroup collada */ - #include <algorithm> #if !defined(WIN32) -#include <iostream> +# include <iostream> #endif /* COLLADABU_ASSERT, may be able to remove later */ @@ -33,20 +32,20 @@ #include "COLLADAFWPolygons.h" extern "C" { - #include "BKE_customdata.h" - #include "BKE_displist.h" - #include "BKE_global.h" - #include "BKE_library.h" - #include "BKE_material.h" - #include "BKE_mesh.h" - #include "BKE_object.h" - - #include "BLI_listbase.h" - #include "BLI_math.h" - #include "BLI_string.h" - #include "BLI_edgehash.h" - - #include "MEM_guardedalloc.h" +#include "BKE_customdata.h" +#include "BKE_displist.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_object.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_edgehash.h" + +#include "MEM_guardedalloc.h" } #include "ArmatureImporter.h" @@ -54,356 +53,370 @@ extern "C" { #include "collada_utils.h" // get node name, or fall back to original id if not present (name is optional) -template<class T> -static const std::string bc_get_dae_name(T *node) +template<class T> static const std::string bc_get_dae_name(T *node) { - return node->getName().size() ? node->getName(): node->getOriginalId(); + return node->getName().size() ? node->getName() : node->getOriginalId(); } static const char *bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type) { - switch (type) { - case COLLADAFW::MeshPrimitive::LINES: - return "LINES"; - case COLLADAFW::MeshPrimitive::LINE_STRIPS: - return "LINESTRIPS"; - case COLLADAFW::MeshPrimitive::POLYGONS: - return "POLYGONS"; - case COLLADAFW::MeshPrimitive::POLYLIST: - return "POLYLIST"; - case COLLADAFW::MeshPrimitive::TRIANGLES: - return "TRIANGLES"; - case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: - return "TRIANGLE_FANS"; - case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS: - return "TRIANGLE_STRIPS"; - case COLLADAFW::MeshPrimitive::POINTS: - return "POINTS"; - case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE: - return "UNDEFINED_PRIMITIVE_TYPE"; - } - return "UNKNOWN"; + switch (type) { + case COLLADAFW::MeshPrimitive::LINES: + return "LINES"; + case COLLADAFW::MeshPrimitive::LINE_STRIPS: + return "LINESTRIPS"; + case COLLADAFW::MeshPrimitive::POLYGONS: + return "POLYGONS"; + case COLLADAFW::MeshPrimitive::POLYLIST: + return "POLYLIST"; + case COLLADAFW::MeshPrimitive::TRIANGLES: + return "TRIANGLES"; + case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: + return "TRIANGLE_FANS"; + case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS: + return "TRIANGLE_STRIPS"; + case COLLADAFW::MeshPrimitive::POINTS: + return "POINTS"; + case COLLADAFW::MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE: + return "UNDEFINED_PRIMITIVE_TYPE"; + } + return "UNKNOWN"; } static const char *bc_geomTypeToStr(COLLADAFW::Geometry::GeometryType type) { - switch (type) { - case COLLADAFW::Geometry::GEO_TYPE_MESH: - return "MESH"; - case COLLADAFW::Geometry::GEO_TYPE_SPLINE: - return "SPLINE"; - case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH: - return "CONVEX_MESH"; - case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN: - default: - return "UNKNOWN"; - } + switch (type) { + case COLLADAFW::Geometry::GEO_TYPE_MESH: + return "MESH"; + case COLLADAFW::Geometry::GEO_TYPE_SPLINE: + return "SPLINE"; + case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH: + return "CONVEX_MESH"; + case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN: + default: + return "UNKNOWN"; + } } - -UVDataWrapper::UVDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata) +UVDataWrapper::UVDataWrapper(COLLADAFW::MeshVertexData &vdata) : mVData(&vdata) { } #ifdef COLLADA_DEBUG void WVDataWrapper::print() { - fprintf(stderr, "UVs:\n"); - switch (mVData->getType()) { - case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: - { - COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues(); - if (values->getCount()) { - for (int i = 0; i < values->getCount(); i += 2) { - fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i + 1]); - } - } - } - break; - case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: - { - COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); - if (values->getCount()) { - for (int i = 0; i < values->getCount(); i += 2) { - fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i + 1]); - } - } - } - break; - } - fprintf(stderr, "\n"); + fprintf(stderr, "UVs:\n"); + switch (mVData->getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: { + COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues(); + if (values->getCount()) { + for (int i = 0; i < values->getCount(); i += 2) { + fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i + 1]); + } + } + } break; + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: { + COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); + if (values->getCount()) { + for (int i = 0; i < values->getCount(); i += 2) { + fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i + 1]); + } + } + } break; + } + fprintf(stderr, "\n"); } #endif void UVDataWrapper::getUV(int uv_index, float *uv) { - int stride = mVData->getStride(0); - if (stride == 0) stride = 2; - - switch (mVData->getType()) { - case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: - { - COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues(); - if (values->empty()) return; - uv[0] = (*values)[uv_index * stride]; - uv[1] = (*values)[uv_index * stride + 1]; - - } - break; - case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: - { - COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); - if (values->empty()) return; - uv[0] = (float)(*values)[uv_index * stride]; - uv[1] = (float)(*values)[uv_index * stride + 1]; - - } - break; - case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN: - default: - fprintf(stderr, "MeshImporter.getUV(): unknown data type\n"); - } + int stride = mVData->getStride(0); + if (stride == 0) + stride = 2; + + switch (mVData->getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: { + COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues(); + if (values->empty()) + return; + uv[0] = (*values)[uv_index * stride]; + uv[1] = (*values)[uv_index * stride + 1]; + + } break; + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: { + COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); + if (values->empty()) + return; + uv[0] = (float)(*values)[uv_index * stride]; + uv[1] = (float)(*values)[uv_index * stride + 1]; + + } break; + case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN: + default: + fprintf(stderr, "MeshImporter.getUV(): unknown data type\n"); + } } -VCOLDataWrapper::VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata) {} +VCOLDataWrapper::VCOLDataWrapper(COLLADAFW::MeshVertexData &vdata) : mVData(&vdata) +{ +} void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol) { - int stride = mVData->getStride(0); - if (stride == 0) stride = 3; - - switch (mVData->getType()) { - case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: - { - COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues(); - if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an error instead - - mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]); - mloopcol->g = unit_float_to_uchar_clamp((*values)[v_index * stride + 1]); - mloopcol->b = unit_float_to_uchar_clamp((*values)[v_index * stride + 2]); - } - break; - - case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: - { - COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); - if (values->empty() || values->getCount() <= (v_index * stride + 2)) return; // xxx need to create an error instead - - mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]); - mloopcol->g = unit_float_to_uchar_clamp((*values)[v_index * stride + 1]); - mloopcol->b = unit_float_to_uchar_clamp((*values)[v_index * stride + 2]); - } - break; - default: - fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n"); - } - + int stride = mVData->getStride(0); + if (stride == 0) + stride = 3; + + switch (mVData->getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: { + COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues(); + if (values->empty() || values->getCount() <= (v_index * stride + 2)) + return; // xxx need to create an error instead + + mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]); + mloopcol->g = unit_float_to_uchar_clamp((*values)[v_index * stride + 1]); + mloopcol->b = unit_float_to_uchar_clamp((*values)[v_index * stride + 2]); + } break; + + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: { + COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); + if (values->empty() || values->getCount() <= (v_index * stride + 2)) + return; // xxx need to create an error instead + + mloopcol->r = unit_float_to_uchar_clamp((*values)[v_index * stride]); + mloopcol->g = unit_float_to_uchar_clamp((*values)[v_index * stride + 1]); + mloopcol->b = unit_float_to_uchar_clamp((*values)[v_index * stride + 2]); + } break; + default: + fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n"); + } } -MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer): - unitconverter(unitconv), - m_bmain(bmain), - scene(sce), - view_layer(view_layer), - armature_importer(arm) +MeshImporter::MeshImporter( + UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer) + : unitconverter(unitconv), + m_bmain(bmain), + scene(sce), + view_layer(view_layer), + armature_importer(arm) { - /* pass */ + /* pass */ } -bool MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count) +bool MeshImporter::set_poly_indices( + MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count) { - mpoly->loopstart = loop_index; - mpoly->totloop = loop_count; - bool broken_loop = false; - for (int index=0; index < loop_count; index++) { - - /* Test if loop defines a hole */ - if (!broken_loop) { - for (int i = 0; i < index; i++) { - if (indices[i] == indices[index]) { - // duplicate index -> not good - broken_loop = true; - } - } - } - - mloop->v = indices[index]; - mloop++; - } - return broken_loop; + mpoly->loopstart = loop_index; + mpoly->totloop = loop_count; + bool broken_loop = false; + for (int index = 0; index < loop_count; index++) { + + /* Test if loop defines a hole */ + if (!broken_loop) { + for (int i = 0; i < index; i++) { + if (indices[i] == indices[index]) { + // duplicate index -> not good + broken_loop = true; + } + } + } + + mloop->v = indices[index]; + mloop++; + } + return broken_loop; } -void MeshImporter::set_vcol(MLoopCol *mlc, VCOLDataWrapper &vob, int loop_index, COLLADAFW::IndexList &index_list, int count) +void MeshImporter::set_vcol(MLoopCol *mlc, + VCOLDataWrapper &vob, + int loop_index, + COLLADAFW::IndexList &index_list, + int count) { - int index; - for (index = 0; index < count; index++, mlc++) { - int v_index = index_list.getIndex(index + loop_index); - vob.get_vcol(v_index,mlc); - } + int index; + for (index = 0; index < count; index++, mlc++) { + int v_index = index_list.getIndex(index + loop_index); + vob.get_vcol(v_index, mlc); + } } -void MeshImporter::set_face_uv(MLoopUV *mloopuv, UVDataWrapper &uvs, - int start_index, COLLADAFW::IndexList& index_list, int count) +void MeshImporter::set_face_uv(MLoopUV *mloopuv, + UVDataWrapper &uvs, + int start_index, + COLLADAFW::IndexList &index_list, + int count) { - // per face vertex indices, this means for quad we have 4 indices, not 8 - COLLADAFW::UIntValuesArray& indices = index_list.getIndices(); + // per face vertex indices, this means for quad we have 4 indices, not 8 + COLLADAFW::UIntValuesArray &indices = index_list.getIndices(); - for (int index = 0; index < count; index++) { - int uv_index = indices[index+start_index]; - uvs.getUV(uv_index, mloopuv[index].uv); - } + for (int index = 0; index < count; index++) { + int uv_index = indices[index + start_index]; + uvs.getUV(uv_index, mloopuv[index].uv); + } } #ifdef COLLADA_DEBUG -void MeshImporter::print_index_list(COLLADAFW::IndexList& index_list) +void MeshImporter::print_index_list(COLLADAFW::IndexList &index_list) { - fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str()); - for (int i = 0; i < index_list.getIndicesCount(); i += 2) { - fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1)); - } - fprintf(stderr, "\n"); + fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str()); + for (int i = 0; i < index_list.getIndicesCount(); i += 2) { + fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1)); + } + fprintf(stderr, "\n"); } #endif -bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has supported primitive types: lines, polylist, triangles, triangle_fans +bool MeshImporter::is_nice_mesh( + COLLADAFW::Mesh * + mesh) // checks if mesh has supported primitive types: lines, polylist, triangles, triangle_fans { - COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives(); - - const std::string &name = bc_get_dae_name(mesh); - - for (unsigned i = 0; i < prim_arr.getCount(); i++) { - - COLLADAFW::MeshPrimitive *mp = prim_arr[i]; - COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType(); - - const char *type_str = bc_primTypeToStr(type); - - // OpenCollada passes POLYGONS type for <polylist> - if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) { - - COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; - COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray(); - - int hole_count = 0; - int nonface_count = 0; - - for (unsigned int j = 0; j < vca.getCount(); j++) { - int count = vca[j]; - if (abs(count) < 3) { - nonface_count++; - } - - if (count < 0) { - hole_count ++; - } - } - - if (hole_count > 0) { - fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count); - } - - if (nonface_count > 0) { - fprintf(stderr, "WARNING: Primitive %s in %s: %d faces with vertex count < 3 (rejected)\n", type_str, name.c_str(), nonface_count); - } - } - - else if (type == COLLADAFW::MeshPrimitive::LINES) { - // TODO: Add Checker for line syntax here - } - - else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { - fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str); - return false; - } - } - - return true; + COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives(); + + const std::string &name = bc_get_dae_name(mesh); + + for (unsigned i = 0; i < prim_arr.getCount(); i++) { + + COLLADAFW::MeshPrimitive *mp = prim_arr[i]; + COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType(); + + const char *type_str = bc_primTypeToStr(type); + + // OpenCollada passes POLYGONS type for <polylist> + if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) { + + COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; + COLLADAFW::Polygons::VertexCountArray &vca = mpvc->getGroupedVerticesVertexCountArray(); + + int hole_count = 0; + int nonface_count = 0; + + for (unsigned int j = 0; j < vca.getCount(); j++) { + int count = vca[j]; + if (abs(count) < 3) { + nonface_count++; + } + + if (count < 0) { + hole_count++; + } + } + + if (hole_count > 0) { + fprintf(stderr, + "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", + type_str, + name.c_str(), + hole_count); + } + + if (nonface_count > 0) { + fprintf(stderr, + "WARNING: Primitive %s in %s: %d faces with vertex count < 3 (rejected)\n", + type_str, + name.c_str(), + nonface_count); + } + } + + else if (type == COLLADAFW::MeshPrimitive::LINES) { + // TODO: Add Checker for line syntax here + } + + else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && + type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { + fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str); + return false; + } + } + + return true; } void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me) { - // vertices - COLLADAFW::MeshVertexData& pos = mesh->getPositions(); - if (pos.empty()) { - return; - } + // vertices + COLLADAFW::MeshVertexData &pos = mesh->getPositions(); + if (pos.empty()) { + return; + } - int stride = pos.getStride(0); - if (stride == 0) stride = 3; + int stride = pos.getStride(0); + if (stride == 0) + stride = 3; - me->totvert = pos.getFloatValues()->getCount() / stride; - me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); + me->totvert = pos.getFloatValues()->getCount() / stride; + me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); - MVert *mvert; - int i; + MVert *mvert; + int i; - for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { - get_vector(mvert->co, pos, i, stride); - } + for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { + get_vector(mvert->co, pos, i, stride); + } } - // ===================================================================== // condition 1: The Primitive has normals // condition 2: The number of normals equals the number of faces. // return true if both conditions apply. // return false otherwise. // ===================================================================== -bool MeshImporter::primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp) { - - bool has_useable_normals = false; - - int normals_count = mp->getNormalIndices().getCount(); - if (normals_count > 0) { - int index_count = mp->getPositionIndices().getCount(); - if (index_count == normals_count) - has_useable_normals = true; - else { - fprintf(stderr, - "Warning: Number of normals %d is different from the number of vertices %d, skipping normals\n", - normals_count, index_count); - } - } - - return has_useable_normals; +bool MeshImporter::primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp) +{ + bool has_useable_normals = false; + + int normals_count = mp->getNormalIndices().getCount(); + if (normals_count > 0) { + int index_count = mp->getPositionIndices().getCount(); + if (index_count == normals_count) + has_useable_normals = true; + else { + fprintf(stderr, + "Warning: Number of normals %d is different from the number of vertices %d, " + "skipping normals\n", + normals_count, + index_count); + } + } + + return has_useable_normals; } // ===================================================================== // Assume that only TRIANGLES, TRIANGLE_FANS, POLYLIST and POLYGONS // have faces. (to be verified) // ===================================================================== -bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) { - - bool has_faces = false; - int type = mp->getPrimitiveType(); - switch (type) { - case COLLADAFW::MeshPrimitive::TRIANGLES: - case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: - case COLLADAFW::MeshPrimitive::POLYLIST: - case COLLADAFW::MeshPrimitive::POLYGONS: - { - has_faces = true; - break; - } - default: { - has_faces = false; - break; - } - } - return has_faces; -} - +bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) +{ -static std::string extract_vcolname(const COLLADAFW::String &collada_id) { - std::string colname = collada_id; - int spos = colname.find("-mesh-colors-"); - if (spos != std::string::npos) { - colname = colname.substr(spos+13); - } - return colname; + bool has_faces = false; + int type = mp->getPrimitiveType(); + switch (type) { + case COLLADAFW::MeshPrimitive::TRIANGLES: + case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: + case COLLADAFW::MeshPrimitive::POLYLIST: + case COLLADAFW::MeshPrimitive::POLYGONS: { + has_faces = true; + break; + } + default: { + has_faces = false; + break; + } + } + return has_faces; } +static std::string extract_vcolname(const COLLADAFW::String &collada_id) +{ + std::string colname = collada_id; + int spos = colname.find("-mesh-colors-"); + if (spos != std::string::npos) { + colname = colname.substr(spos + 13); + } + return colname; +} // ================================================================= // Return the number of faces by summing up @@ -413,130 +426,128 @@ static std::string extract_vcolname(const COLLADAFW::String &collada_id) { // ================================================================= void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) { - COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives(); - int total_poly_count = 0; - int total_loop_count = 0; - - // collect edge_count and face_count from all parts - for (int i = 0; i < prim_arr.getCount(); i++) { - COLLADAFW::MeshPrimitive *mp = prim_arr[i]; - int type = mp->getPrimitiveType(); - switch (type) { - case COLLADAFW::MeshPrimitive::TRIANGLES: - case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: - case COLLADAFW::MeshPrimitive::POLYLIST: - case COLLADAFW::MeshPrimitive::POLYGONS: - { - COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; - size_t prim_poly_count = mpvc->getFaceCount(); - - size_t prim_loop_count = 0; - for (int index=0; index < prim_poly_count; index++) - { - int vcount = get_vertex_count(mpvc, index); - if (vcount > 0) { - prim_loop_count += vcount; - total_poly_count++; - } - else { - // TODO: this is a hole and not another polygon! - } - } - - total_loop_count += prim_loop_count; - - break; - } - default: - break; - } - } - - // Add the data containers - if (total_poly_count > 0) { - me->totpoly = total_poly_count; - me->totloop = total_loop_count; - me->mpoly = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly); - me->mloop = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop); - - unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount(); - for (int i = 0; i < totuvset; i++) { - if (collada_mesh->getUVCoords().getLength(i) == 0) { - totuvset = 0; - break; - } - } - - if (totuvset > 0) { - for (int i = 0; i < totuvset; i++) { - COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i]; - COLLADAFW::String &uvname = info->mName; - // Allocate space for UV_data - CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str()); - } - // activate the first uv map - me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0); - } - - int totcolset = collada_mesh->getColors().getInputInfosArray().getCount(); - if (totcolset > 0) { - for (int i = 0; i < totcolset; i++) { - COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i]; - COLLADAFW::String colname = extract_vcolname(info->mName); - CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str()); - } - me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0); - } - - } + COLLADAFW::MeshPrimitiveArray &prim_arr = collada_mesh->getMeshPrimitives(); + int total_poly_count = 0; + int total_loop_count = 0; + + // collect edge_count and face_count from all parts + for (int i = 0; i < prim_arr.getCount(); i++) { + COLLADAFW::MeshPrimitive *mp = prim_arr[i]; + int type = mp->getPrimitiveType(); + switch (type) { + case COLLADAFW::MeshPrimitive::TRIANGLES: + case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: + case COLLADAFW::MeshPrimitive::POLYLIST: + case COLLADAFW::MeshPrimitive::POLYGONS: { + COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; + size_t prim_poly_count = mpvc->getFaceCount(); + + size_t prim_loop_count = 0; + for (int index = 0; index < prim_poly_count; index++) { + int vcount = get_vertex_count(mpvc, index); + if (vcount > 0) { + prim_loop_count += vcount; + total_poly_count++; + } + else { + // TODO: this is a hole and not another polygon! + } + } + + total_loop_count += prim_loop_count; + + break; + } + default: + break; + } + } + + // Add the data containers + if (total_poly_count > 0) { + me->totpoly = total_poly_count; + me->totloop = total_loop_count; + me->mpoly = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly); + me->mloop = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop); + + unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount(); + for (int i = 0; i < totuvset; i++) { + if (collada_mesh->getUVCoords().getLength(i) == 0) { + totuvset = 0; + break; + } + } + + if (totuvset > 0) { + for (int i = 0; i < totuvset; i++) { + COLLADAFW::MeshVertexData::InputInfos *info = + collada_mesh->getUVCoords().getInputInfosArray()[i]; + COLLADAFW::String &uvname = info->mName; + // Allocate space for UV_data + CustomData_add_layer_named( + &me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str()); + } + // activate the first uv map + me->mloopuv = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0); + } + + int totcolset = collada_mesh->getColors().getInputInfosArray().getCount(); + if (totcolset > 0) { + for (int i = 0; i < totcolset; i++) { + COLLADAFW::MeshVertexData::InputInfos *info = + collada_mesh->getColors().getInputInfosArray()[i]; + COLLADAFW::String colname = extract_vcolname(info->mName); + CustomData_add_layer_named( + &me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, colname.c_str()); + } + me->mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0); + } + } } -unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) { - int type = mp->getPrimitiveType(); - int result; - switch (type) { - case COLLADAFW::MeshPrimitive::TRIANGLES: - case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: - { - result = 3; - break; - } - case COLLADAFW::MeshPrimitive::POLYLIST: - case COLLADAFW::MeshPrimitive::POLYGONS: - { - result = mp->getGroupedVerticesVertexCountArray()[index]; - break; - } - default: - { - result = -1; - break; - } - } - return result; +unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) +{ + int type = mp->getPrimitiveType(); + int result; + switch (type) { + case COLLADAFW::MeshPrimitive::TRIANGLES: + case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: { + result = 3; + break; + } + case COLLADAFW::MeshPrimitive::POLYLIST: + case COLLADAFW::MeshPrimitive::POLYGONS: { + result = mp->getGroupedVerticesVertexCountArray()[index]; + break; + } + default: { + result = -1; + break; + } + } + return result; } - -unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) { - COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives(); - int loose_edge_count = 0; - - // collect edge_count and face_count from all parts - for (int i = 0; i < prim_arr.getCount(); i++) { - COLLADAFW::MeshPrimitive *mp = prim_arr[i]; - int type = mp->getPrimitiveType(); - switch (type) { - case COLLADAFW::MeshPrimitive::LINES: - { - size_t prim_totface = mp->getFaceCount(); - loose_edge_count += prim_totface; - break; - } - default: - break; - } - } - return loose_edge_count; +unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) +{ + COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives(); + int loose_edge_count = 0; + + // collect edge_count and face_count from all parts + for (int i = 0; i < prim_arr.getCount(); i++) { + COLLADAFW::MeshPrimitive *mp = prim_arr[i]; + int type = mp->getPrimitiveType(); + switch (type) { + case COLLADAFW::MeshPrimitive::LINES: { + size_t prim_totface = mp->getFaceCount(); + loose_edge_count += prim_totface; + break; + } + default: + break; + } + } + return loose_edge_count; } // ================================================================= @@ -548,32 +559,32 @@ unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) { // ================================================================= void MeshImporter::mesh_add_edges(Mesh *mesh, int len) { - CustomData edata; - MEdge *medge; - int totedge; + CustomData edata; + MEdge *medge; + int totedge; - if (len == 0) - return; + if (len == 0) + return; - totedge = mesh->totedge + len; + totedge = mesh->totedge + len; - /* update customdata */ - CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge); - CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge); + /* update customdata */ + CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge); + CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge); - if (!CustomData_has_layer(&edata, CD_MEDGE)) - CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); + if (!CustomData_has_layer(&edata, CD_MEDGE)) + CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); - CustomData_free(&mesh->edata, mesh->totedge); - mesh->edata = edata; - BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */ + CustomData_free(&mesh->edata, mesh->totedge); + mesh->edata = edata; + BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */ - /* set default flags */ - medge = &mesh->medge[mesh->totedge]; - for (int i = 0; i < len; i++, medge++) - medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; + /* set default flags */ + medge = &mesh->medge[mesh->totedge]; + for (int i = 0; i < len; i++, medge++) + medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; - mesh->totedge = totedge; + mesh->totedge = totedge; } // ================================================================= @@ -584,39 +595,37 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len) // ================================================================= void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) { - unsigned int loose_edge_count = get_loose_edge_count(mesh); - if (loose_edge_count > 0) { - - unsigned int face_edge_count = me->totedge; - /* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */ - - mesh_add_edges(me, loose_edge_count); - MEdge *med = me->medge + face_edge_count; - - COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives(); - - for (int index = 0; index < prim_arr.getCount(); index++) { - COLLADAFW::MeshPrimitive *mp = prim_arr[index]; - - int type = mp->getPrimitiveType(); - if (type == COLLADAFW::MeshPrimitive::LINES) { - unsigned int edge_count = mp->getFaceCount(); - unsigned int *indices = mp->getPositionIndices().getData(); - - for (int j = 0; j < edge_count; j++, med++) { - med->bweight = 0; - med->crease = 0; - med->flag |= ME_LOOSEEDGE; - med->v1 = indices[2 * j]; - med->v2 = indices[2 * j + 1]; - } - } - } - - } + unsigned int loose_edge_count = get_loose_edge_count(mesh); + if (loose_edge_count > 0) { + + unsigned int face_edge_count = me->totedge; + /* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */ + + mesh_add_edges(me, loose_edge_count); + MEdge *med = me->medge + face_edge_count; + + COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives(); + + for (int index = 0; index < prim_arr.getCount(); index++) { + COLLADAFW::MeshPrimitive *mp = prim_arr[index]; + + int type = mp->getPrimitiveType(); + if (type == COLLADAFW::MeshPrimitive::LINES) { + unsigned int edge_count = mp->getFaceCount(); + unsigned int *indices = mp->getPositionIndices().getData(); + + for (int j = 0; j < edge_count; j++, med++) { + med->bweight = 0; + med->crease = 0; + med->flag |= ME_LOOSEEDGE; + med->v1 = indices[2 * j]; + med->v2 = indices[2 * j + 1]; + } + } + } + } } - // ======================================================================= // Read all faces from TRIANGLES, TRIANGLE_FANS, POLYLIST, POLYGON // Important: This function MUST be called before read_lines() @@ -626,252 +635,260 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) // ======================================================================== void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) { - unsigned int i; - - allocate_poly_data(collada_mesh, me); - - UVDataWrapper uvs(collada_mesh->getUVCoords()); - VCOLDataWrapper vcol(collada_mesh->getColors()); - - MPoly *mpoly = me->mpoly; - MLoop *mloop = me->mloop; - int loop_index = 0; - - MaterialIdPrimitiveArrayMap mat_prim_map; - - COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives(); - COLLADAFW::MeshVertexData& nor = collada_mesh->getNormals(); - - for (i = 0; i < prim_arr.getCount(); i++) { - - COLLADAFW::MeshPrimitive *mp = prim_arr[i]; - - // faces - size_t prim_totpoly = mp->getFaceCount(); - unsigned int *position_indices = mp->getPositionIndices().getData(); - unsigned int *normal_indices = mp->getNormalIndices().getData(); - - - bool mp_has_normals = primitive_has_useable_normals(mp); - bool mp_has_faces = primitive_has_faces(mp); - - int collada_meshtype = mp->getPrimitiveType(); - - // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive - Primitive prim = {mpoly, 0}; - - // If MeshPrimitive is TRIANGLE_FANS we split it into triangles - // The first trifan vertex will be the first vertex in every triangle - // XXX The proper function of TRIANGLE_FANS is not tested!!! - // XXX In particular the handling of the normal_indices looks very wrong to me - if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { - unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount(); - for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) { - unsigned int first_vertex = position_indices[0]; // Store first trifan vertex - unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal - unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index); - - for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) { - // For each triangle store indices of its 3 vertices - unsigned int triangle_vertex_indices[3] = {first_vertex, position_indices[1], position_indices[2]}; - set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3); - - if (mp_has_normals) { // vertex normals, same inplementation as for the triangles - // the same for vertces normals - unsigned int vertex_normal_indices[3] = {first_normal, normal_indices[1], normal_indices[2]}; - if (!is_flat_face(vertex_normal_indices, nor, 3)) - mpoly->flag |= ME_SMOOTH; - normal_indices++; - } - - mpoly++; - mloop += 3; - loop_index += 3; - prim.totpoly++; - - } - - // Moving cursor to the next triangle fan. - if (mp_has_normals) - normal_indices += 2; - - position_indices += 2; - } - } - - if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST || - collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS || - collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) - { - COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; - unsigned int start_index = 0; - - COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray(); - COLLADAFW::IndexListArray& index_list_array_vcolor = mp->getColorIndicesArray(); - - int invalid_loop_holes = 0; - for (unsigned int j = 0; j < prim_totpoly; j++) { - - // Vertices in polygon: - int vcount = get_vertex_count(mpvc, j); - if (vcount < 0) { - continue; // TODO: add support for holes - } - - bool broken_loop = set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount); - if (broken_loop) - { - invalid_loop_holes += 1; - } - - for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) { - // get mtface by face index and uv set index - COLLADAFW::IndexList& index_list = *index_list_array_uvcoord[uvset_index]; - MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, index_list.getName().c_str()); - if (mloopuv == NULL) { - fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n", me->id.name, index_list.getName().c_str() ); - } - else { - set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array_uvcoord[uvset_index], vcount); - } - } - - if (mp_has_normals) { - if (!is_flat_face(normal_indices, nor, vcount)) - mpoly->flag |= ME_SMOOTH; - } - - - if (mp->hasColorIndices()) { - int vcolor_count = index_list_array_vcolor.getCount(); - - for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) { - - COLLADAFW::IndexList& color_index_list = *mp->getColorIndices(vcolor_index); - COLLADAFW::String colname = extract_vcolname(color_index_list.getName()); - MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str()); - if (mloopcol == NULL) { - fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, color_index_list.getName().c_str()); - } - else { - set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount); - } - } - } - - mpoly++; - mloop += vcount; - loop_index += vcount; - start_index += vcount; - prim.totpoly++; - - if (mp_has_normals) - normal_indices += vcount; - - position_indices += vcount; - } - - if (invalid_loop_holes > 0) - { - fprintf(stderr, "Collada import: Mesh [%s] : contains %d unsupported loops (holes).\n", me->id.name, invalid_loop_holes); - } - } - - else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) { - continue; // read the lines later after all the rest is done - } - - if (mp_has_faces) - mat_prim_map[mp->getMaterialId()].push_back(prim); - - - } - - geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map; + unsigned int i; + + allocate_poly_data(collada_mesh, me); + + UVDataWrapper uvs(collada_mesh->getUVCoords()); + VCOLDataWrapper vcol(collada_mesh->getColors()); + + MPoly *mpoly = me->mpoly; + MLoop *mloop = me->mloop; + int loop_index = 0; + + MaterialIdPrimitiveArrayMap mat_prim_map; + + COLLADAFW::MeshPrimitiveArray &prim_arr = collada_mesh->getMeshPrimitives(); + COLLADAFW::MeshVertexData &nor = collada_mesh->getNormals(); + + for (i = 0; i < prim_arr.getCount(); i++) { + + COLLADAFW::MeshPrimitive *mp = prim_arr[i]; + + // faces + size_t prim_totpoly = mp->getFaceCount(); + unsigned int *position_indices = mp->getPositionIndices().getData(); + unsigned int *normal_indices = mp->getNormalIndices().getData(); + + bool mp_has_normals = primitive_has_useable_normals(mp); + bool mp_has_faces = primitive_has_faces(mp); + + int collada_meshtype = mp->getPrimitiveType(); + + // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive + Primitive prim = {mpoly, 0}; + + // If MeshPrimitive is TRIANGLE_FANS we split it into triangles + // The first trifan vertex will be the first vertex in every triangle + // XXX The proper function of TRIANGLE_FANS is not tested!!! + // XXX In particular the handling of the normal_indices looks very wrong to me + if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { + unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount(); + for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) { + unsigned int first_vertex = position_indices[0]; // Store first trifan vertex + unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal + unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index); + + for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) { + // For each triangle store indices of its 3 vertices + unsigned int triangle_vertex_indices[3] = { + first_vertex, position_indices[1], position_indices[2]}; + set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3); + + if (mp_has_normals) { // vertex normals, same inplementation as for the triangles + // the same for vertces normals + unsigned int vertex_normal_indices[3] = { + first_normal, normal_indices[1], normal_indices[2]}; + if (!is_flat_face(vertex_normal_indices, nor, 3)) + mpoly->flag |= ME_SMOOTH; + normal_indices++; + } + + mpoly++; + mloop += 3; + loop_index += 3; + prim.totpoly++; + } + + // Moving cursor to the next triangle fan. + if (mp_has_normals) + normal_indices += 2; + + position_indices += 2; + } + } + + if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST || + collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS || + collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) { + COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; + unsigned int start_index = 0; + + COLLADAFW::IndexListArray &index_list_array_uvcoord = mp->getUVCoordIndicesArray(); + COLLADAFW::IndexListArray &index_list_array_vcolor = mp->getColorIndicesArray(); + + int invalid_loop_holes = 0; + for (unsigned int j = 0; j < prim_totpoly; j++) { + + // Vertices in polygon: + int vcount = get_vertex_count(mpvc, j); + if (vcount < 0) { + continue; // TODO: add support for holes + } + + bool broken_loop = set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount); + if (broken_loop) { + invalid_loop_holes += 1; + } + + for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); + uvset_index++) { + // get mtface by face index and uv set index + COLLADAFW::IndexList &index_list = *index_list_array_uvcoord[uvset_index]; + MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_named( + &me->ldata, CD_MLOOPUV, index_list.getName().c_str()); + if (mloopuv == NULL) { + fprintf(stderr, + "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n", + me->id.name, + index_list.getName().c_str()); + } + else { + set_face_uv(mloopuv + loop_index, + uvs, + start_index, + *index_list_array_uvcoord[uvset_index], + vcount); + } + } + + if (mp_has_normals) { + if (!is_flat_face(normal_indices, nor, vcount)) + mpoly->flag |= ME_SMOOTH; + } + + if (mp->hasColorIndices()) { + int vcolor_count = index_list_array_vcolor.getCount(); + + for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) { + + COLLADAFW::IndexList &color_index_list = *mp->getColorIndices(vcolor_index); + COLLADAFW::String colname = extract_vcolname(color_index_list.getName()); + MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named( + &me->ldata, CD_MLOOPCOL, colname.c_str()); + if (mloopcol == NULL) { + fprintf(stderr, + "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", + me->id.name, + color_index_list.getName().c_str()); + } + else { + set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount); + } + } + } + + mpoly++; + mloop += vcount; + loop_index += vcount; + start_index += vcount; + prim.totpoly++; + + if (mp_has_normals) + normal_indices += vcount; + + position_indices += vcount; + } + + if (invalid_loop_holes > 0) { + fprintf(stderr, + "Collada import: Mesh [%s] : contains %d unsupported loops (holes).\n", + me->id.name, + invalid_loop_holes); + } + } + + else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) { + continue; // read the lines later after all the rest is done + } + + if (mp_has_faces) + mat_prim_map[mp->getMaterialId()].push_back(prim); + } + + geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map; } -void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride) +void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData &arr, int i, int stride) { - i *= stride; - - switch (arr.getType()) { - case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: - { - COLLADAFW::ArrayPrimitiveType<float> *values = arr.getFloatValues(); - if (values->empty()) return; - - v[0] = (*values)[i++]; - v[1] = (*values)[i++]; - if (stride>=3) { - v[2] = (*values)[i]; - } - else { - v[2] = 0.0f; - } - - } - break; - case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: - { - COLLADAFW::ArrayPrimitiveType<double> *values = arr.getDoubleValues(); - if (values->empty()) return; - - v[0] = (float)(*values)[i++]; - v[1] = (float)(*values)[i++]; - if (stride >= 3) { - v[2] = (float)(*values)[i]; - } - else { - v[2] = 0.0f; - } - } - break; - default: - break; - } + i *= stride; + + switch (arr.getType()) { + case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT: { + COLLADAFW::ArrayPrimitiveType<float> *values = arr.getFloatValues(); + if (values->empty()) + return; + + v[0] = (*values)[i++]; + v[1] = (*values)[i++]; + if (stride >= 3) { + v[2] = (*values)[i]; + } + else { + v[2] = 0.0f; + } + + } break; + case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE: { + COLLADAFW::ArrayPrimitiveType<double> *values = arr.getDoubleValues(); + if (values->empty()) + return; + + v[0] = (float)(*values)[i++]; + v[1] = (float)(*values)[i++]; + if (stride >= 3) { + v[2] = (float)(*values)[i]; + } + else { + v[2] = 0.0f; + } + } break; + default: + break; + } } -bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count) +bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData &nor, int count) { - float a[3], b[3]; + float a[3], b[3]; - get_vector(a, nor, *nind, 3); - normalize_v3(a); + get_vector(a, nor, *nind, 3); + normalize_v3(a); - nind++; + nind++; - for (int i = 1; i < count; i++, nind++) { - get_vector(b, nor, *nind, 3); - normalize_v3(b); + for (int i = 1; i < count; i++, nind++) { + get_vector(b, nor, *nind, 3); + normalize_v3(b); - float dp = dot_v3v3(a, b); + float dp = dot_v3v3(a, b); - if (dp < 0.99999f || dp > 1.00001f) - return false; - } + if (dp < 0.99999f || dp > 1.00001f) + return false; + } - return true; + return true; } -Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid) +Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId &geom_uid) { - if (uid_object_map.find(geom_uid) != uid_object_map.end()) - return uid_object_map[geom_uid]; - return NULL; + if (uid_object_map.find(geom_uid) != uid_object_map.end()) + return uid_object_map[geom_uid]; + return NULL; } -Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid) +Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId &mesh_uid) { - if (uid_mesh_map.find(mesh_uid) != uid_mesh_map.end()) - return uid_mesh_map[mesh_uid]; - return NULL; + if (uid_mesh_map.find(mesh_uid) != uid_mesh_map.end()) + return uid_mesh_map[mesh_uid]; + return NULL; } std::string *MeshImporter::get_geometry_name(const std::string &mesh_name) { - if (this->mesh_geom_map.find(mesh_name) != this->mesh_geom_map.end()) - return &this->mesh_geom_map[mesh_name]; - return NULL; + if (this->mesh_geom_map.find(mesh_name) != this->mesh_geom_map.end()) + return &this->mesh_geom_map[mesh_name]; + return NULL; } /** @@ -881,18 +898,22 @@ std::string *MeshImporter::get_geometry_name(const std::string &mesh_name) */ static bool bc_has_same_material_configuration(Object *ob1, Object *ob2) { - if (ob1->totcol != ob2->totcol) return false; // not same number of materials - if (ob1->totcol == 0) return false; // no material at all - - for (int index=0; index < ob1->totcol; index++) { - if (ob1->matbits[index] != ob2->matbits[index]) return false; // shouldn't happen - if (ob1->matbits[index] == 0) return false; // shouldn't happen - if (ob1->mat[index] != ob2->mat[index]) return false; // different material assignment - } - return true; + if (ob1->totcol != ob2->totcol) + return false; // not same number of materials + if (ob1->totcol == 0) + return false; // no material at all + + for (int index = 0; index < ob1->totcol; index++) { + if (ob1->matbits[index] != ob2->matbits[index]) + return false; // shouldn't happen + if (ob1->matbits[index] == 0) + return false; // shouldn't happen + if (ob1->mat[index] != ob2->mat[index]) + return false; // different material assignment + } + return true; } - /** * * Caution here: This code assumes that all materials are assigned to Object @@ -902,10 +923,10 @@ static bool bc_has_same_material_configuration(Object *ob1, Object *ob2) */ static void bc_copy_materials_to_data(Object *ob, Mesh *me) { - for (int index = 0; index < ob->totcol; index++) { - ob->matbits[index] = 0; - me->mat[index] = ob->mat[index]; - } + for (int index = 0; index < ob->totcol; index++) { + ob->matbits[index] = 0; + me->mat[index] = ob->mat[index]; + } } /** @@ -915,10 +936,10 @@ static void bc_copy_materials_to_data(Object *ob, Mesh *me) */ static void bc_remove_materials_from_object(Object *ob, Mesh *me) { - for (int index = 0; index < ob->totcol; index++) { - ob->matbits[index] = 0; - ob->mat[index] = NULL; - } + for (int index = 0; index < ob->totcol; index++) { + ob->matbits[index] = 0; + ob->mat[index] = NULL; + } } /** @@ -928,19 +949,18 @@ static void bc_remove_materials_from_object(Object *ob, Mesh *me) */ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) { - std::vector<Object *> mesh_users; - for (std::vector<Object *>::iterator it = imported_objects.begin(); - it != imported_objects.end(); ++it) - { - Object *ob = (*it); - if (bc_is_marked(ob)) { - bc_remove_mark(ob); - Mesh *me = (Mesh *) ob->data; - if (me == reference_mesh) - mesh_users.push_back(ob); - } - } - return mesh_users; + std::vector<Object *> mesh_users; + for (std::vector<Object *>::iterator it = imported_objects.begin(); it != imported_objects.end(); + ++it) { + Object *ob = (*it); + if (bc_is_marked(ob)) { + bc_remove_mark(ob); + Mesh *me = (Mesh *)ob->data; + if (me == reference_mesh) + mesh_users.push_back(ob); + } + } + return mesh_users; } /** @@ -963,40 +983,37 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) */ void MeshImporter::optimize_material_assignements() { - for (std::vector<Object *>::iterator it = imported_objects.begin(); - it != imported_objects.end(); ++it) - { - Object *ob = (*it); - Mesh *me = (Mesh *) ob->data; - if (me->id.us==1) { - bc_copy_materials_to_data(ob, me); - bc_remove_materials_from_object(ob, me); - bc_remove_mark(ob); - } - else if (me->id.us > 1) - { - bool can_move = true; - std::vector<Object *> mesh_users = get_all_users_of(me); - if (mesh_users.size() > 1) - { - Object *ref_ob = mesh_users[0]; - for (int index = 1; index < mesh_users.size(); index++) { - if (!bc_has_same_material_configuration(ref_ob, mesh_users[index])) { - can_move = false; - break; - } - } - if (can_move) { - bc_copy_materials_to_data(ref_ob, me); - for (int index = 0; index < mesh_users.size(); index++) { - Object *object = mesh_users[index]; - bc_remove_materials_from_object(object, me); - bc_remove_mark(object); - } - } - } - } - } + for (std::vector<Object *>::iterator it = imported_objects.begin(); it != imported_objects.end(); + ++it) { + Object *ob = (*it); + Mesh *me = (Mesh *)ob->data; + if (me->id.us == 1) { + bc_copy_materials_to_data(ob, me); + bc_remove_materials_from_object(ob, me); + bc_remove_mark(ob); + } + else if (me->id.us > 1) { + bool can_move = true; + std::vector<Object *> mesh_users = get_all_users_of(me); + if (mesh_users.size() > 1) { + Object *ref_ob = mesh_users[0]; + for (int index = 1; index < mesh_users.size(); index++) { + if (!bc_has_same_material_configuration(ref_ob, mesh_users[index])) { + can_move = false; + break; + } + } + if (can_move) { + bc_copy_materials_to_data(ref_ob, me); + for (int index = 0; index < mesh_users.size(); index++) { + Object *object = mesh_users[index]; + bc_remove_materials_from_object(object, me); + bc_remove_mark(object); + } + } + } + } + } } /** @@ -1008,155 +1025,158 @@ void MeshImporter::optimize_material_assignements() * optimize_material_assignements() above. */ void MeshImporter::assign_material_to_geom( - COLLADAFW::MaterialBinding cmaterial, - std::map<COLLADAFW::UniqueId, Material *>& uid_material_map, - Object *ob, const COLLADAFW::UniqueId *geom_uid, - short mat_index) + COLLADAFW::MaterialBinding cmaterial, + std::map<COLLADAFW::UniqueId, Material *> &uid_material_map, + Object *ob, + const COLLADAFW::UniqueId *geom_uid, + short mat_index) { - const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial(); + const COLLADAFW::UniqueId &ma_uid = cmaterial.getReferencedMaterial(); - // do we know this material? - if (uid_material_map.find(ma_uid) == uid_material_map.end()) { + // do we know this material? + if (uid_material_map.find(ma_uid) == uid_material_map.end()) { - fprintf(stderr, "Cannot find material by UID.\n"); - return; - } + fprintf(stderr, "Cannot find material by UID.\n"); + return; + } - // first time we get geom_uid, ma_uid pair. Save for later check. - materials_mapped_to_geom.insert(std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid)); + // first time we get geom_uid, ma_uid pair. Save for later check. + materials_mapped_to_geom.insert( + std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid)); - Material *ma = uid_material_map[ma_uid]; + Material *ma = uid_material_map[ma_uid]; - // Attention! This temporarily assigns material to object on purpose! - // See note above. - ob->actcol=0; - assign_material(m_bmain, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT); + // Attention! This temporarily assigns material to object on purpose! + // See note above. + ob->actcol = 0; + assign_material(m_bmain, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT); - MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid]; - COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId(); + MaterialIdPrimitiveArrayMap &mat_prim_map = geom_uid_mat_mapping_map[*geom_uid]; + COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId(); - // assign material indices to mesh faces - if (mat_prim_map.find(mat_id) != mat_prim_map.end()) { + // assign material indices to mesh faces + if (mat_prim_map.find(mat_id) != mat_prim_map.end()) { - std::vector<Primitive>& prims = mat_prim_map[mat_id]; + std::vector<Primitive> &prims = mat_prim_map[mat_id]; - std::vector<Primitive>::iterator it; + std::vector<Primitive>::iterator it; - for (it = prims.begin(); it != prims.end(); it++) { - Primitive& prim = *it; - MPoly *mpoly = prim.mpoly; + for (it = prims.begin(); it != prims.end(); it++) { + Primitive &prim = *it; + MPoly *mpoly = prim.mpoly; - for (int i = 0; i < prim.totpoly; i++, mpoly++) { - mpoly->mat_nr = mat_index; - } - } - } + for (int i = 0; i < prim.totpoly; i++, mpoly++) { + mpoly->mat_nr = mat_index; + } + } + } } -Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom, - bool isController, - std::map<COLLADAFW::UniqueId, Material *>& uid_material_map) +Object *MeshImporter::create_mesh_object( + COLLADAFW::Node *node, + COLLADAFW::InstanceGeometry *geom, + bool isController, + std::map<COLLADAFW::UniqueId, Material *> &uid_material_map) { - const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId(); - - // check if node instantiates controller or geometry - if (isController) { - - geom_uid = armature_importer->get_geometry_uid(*geom_uid); - - if (!geom_uid) { - fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n"); - return NULL; - } - } - else { - - if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) { - // this could happen if a mesh was not created - // (e.g. if it contains unsupported geometry) - fprintf(stderr, "Couldn't find a mesh by UID.\n"); - return NULL; - } - } - if (!uid_mesh_map[*geom_uid]) return NULL; - - // name Object - const std::string& id = node->getName().size() ? node->getName() : node->getOriginalId(); - const char *name = (id.length()) ? id.c_str() : NULL; - - // add object - Object *ob = bc_add_object(m_bmain, scene, view_layer, OB_MESH, name); - bc_set_mark(ob); // used later for material assignment optimization - - - // store object pointer for ArmatureImporter - uid_object_map[*geom_uid] = ob; - imported_objects.push_back(ob); - - // replace ob->data freeing the old one - Mesh *old_mesh = (Mesh *)ob->data; - Mesh *new_mesh = uid_mesh_map[*geom_uid]; - - BKE_mesh_assign_object(m_bmain, ob, new_mesh); - BKE_mesh_calc_normals(new_mesh); - - id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */ - BKE_id_free_us(m_bmain, old_mesh); - - COLLADAFW::MaterialBindingArray& mat_array = - geom->getMaterialBindings(); - - // loop through geom's materials - for (unsigned int i = 0; i < mat_array.getCount(); i++) { - - if (mat_array[i].getReferencedMaterial().isValid()) { - assign_material_to_geom( - mat_array[i], uid_material_map, ob, geom_uid, - i); - } - else { - fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str()); - } - } - - // clean up the mesh - BKE_mesh_validate((Mesh *)ob->data, false, false); - - return ob; + const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId(); + + // check if node instantiates controller or geometry + if (isController) { + + geom_uid = armature_importer->get_geometry_uid(*geom_uid); + + if (!geom_uid) { + fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n"); + return NULL; + } + } + else { + + if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) { + // this could happen if a mesh was not created + // (e.g. if it contains unsupported geometry) + fprintf(stderr, "Couldn't find a mesh by UID.\n"); + return NULL; + } + } + if (!uid_mesh_map[*geom_uid]) + return NULL; + + // name Object + const std::string &id = node->getName().size() ? node->getName() : node->getOriginalId(); + const char *name = (id.length()) ? id.c_str() : NULL; + + // add object + Object *ob = bc_add_object(m_bmain, scene, view_layer, OB_MESH, name); + bc_set_mark(ob); // used later for material assignment optimization + + // store object pointer for ArmatureImporter + uid_object_map[*geom_uid] = ob; + imported_objects.push_back(ob); + + // replace ob->data freeing the old one + Mesh *old_mesh = (Mesh *)ob->data; + Mesh *new_mesh = uid_mesh_map[*geom_uid]; + + BKE_mesh_assign_object(m_bmain, ob, new_mesh); + BKE_mesh_calc_normals(new_mesh); + + id_us_plus( + &old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */ + BKE_id_free_us(m_bmain, old_mesh); + + COLLADAFW::MaterialBindingArray &mat_array = geom->getMaterialBindings(); + + // loop through geom's materials + for (unsigned int i = 0; i < mat_array.getCount(); i++) { + + if (mat_array[i].getReferencedMaterial().isValid()) { + assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid, i); + } + else { + fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str()); + } + } + + // clean up the mesh + BKE_mesh_validate((Mesh *)ob->data, false, false); + + return ob; } // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom) { - if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) { - // TODO: report warning - fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType())); - return true; - } - - COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh *)geom; - - if (!is_nice_mesh(mesh)) { - fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh).c_str()); - return true; - } - - const std::string& str_geom_id = mesh->getName().size() ? mesh->getName() : mesh->getOriginalId(); - Mesh *me = BKE_mesh_add(m_bmain, (char *)str_geom_id.c_str()); - id_us_min(&me->id); // is already 1 here, but will be set later in BKE_mesh_assign_object - - // store the Mesh pointer to link it later with an Object - // mesh_geom_map needed to map mesh to its geometry name (for shape key naming) - this->uid_mesh_map[mesh->getUniqueId()] = me; - this->mesh_geom_map[std::string(me->id.name)] = str_geom_id; - - read_vertices(mesh, me); - read_polys(mesh, me); - BKE_mesh_calc_edges(me, false, false); - // read_lines() must be called after the face edges have been generated. - // Otherwise the loose edges will be silently deleted again. - read_lines(mesh, me); - - return true; + if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) { + // TODO: report warning + fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType())); + return true; + } + + COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh *)geom; + + if (!is_nice_mesh(mesh)) { + fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh).c_str()); + return true; + } + + const std::string &str_geom_id = mesh->getName().size() ? mesh->getName() : + mesh->getOriginalId(); + Mesh *me = BKE_mesh_add(m_bmain, (char *)str_geom_id.c_str()); + id_us_min(&me->id); // is already 1 here, but will be set later in BKE_mesh_assign_object + + // store the Mesh pointer to link it later with an Object + // mesh_geom_map needed to map mesh to its geometry name (for shape key naming) + this->uid_mesh_map[mesh->getUniqueId()] = me; + this->mesh_geom_map[std::string(me->id.name)] = str_geom_id; + + read_vertices(mesh, me); + read_polys(mesh, me); + BKE_mesh_calc_edges(me, false, false); + // read_lines() must be called after the face edges have been generated. + // Otherwise the loose edges will be silently deleted again. + read_lines(mesh, me); + + return true; } diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h index 08b7edd2a3b..68ab6e73732 100644 --- a/source/blender/collada/MeshImporter.h +++ b/source/blender/collada/MeshImporter.h @@ -45,141 +45,136 @@ extern "C" { #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" - } // only for ArmatureImporter to "see" MeshImporter::get_object_by_geom_uid -class MeshImporterBase -{ -public: - virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid) = 0; - virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid) = 0; - virtual std::string *get_geometry_name(const std::string &mesh_name) = 0; +class MeshImporterBase { + public: + virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId &geom_uid) = 0; + virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId &mesh_uid) = 0; + virtual std::string *get_geometry_name(const std::string &mesh_name) = 0; }; -class UVDataWrapper -{ - COLLADAFW::MeshVertexData *mVData; -public: - UVDataWrapper(COLLADAFW::MeshVertexData& vdata); +class UVDataWrapper { + COLLADAFW::MeshVertexData *mVData; + + public: + UVDataWrapper(COLLADAFW::MeshVertexData &vdata); #ifdef COLLADA_DEBUG - void print(); + void print(); #endif - void getUV(int uv_index, float *uv); + void getUV(int uv_index, float *uv); }; -class VCOLDataWrapper -{ - COLLADAFW::MeshVertexData *mVData; -public: - VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata); - void get_vcol(int v_index, MLoopCol *mloopcol); +class VCOLDataWrapper { + COLLADAFW::MeshVertexData *mVData; + + public: + VCOLDataWrapper(COLLADAFW::MeshVertexData &vdata); + void get_vcol(int v_index, MLoopCol *mloopcol); }; -class MeshImporter : public MeshImporterBase -{ -private: - - UnitConverter *unitconverter; - - Main *m_bmain; - Scene *scene; - ViewLayer *view_layer; - - ArmatureImporter *armature_importer; - - std::map<std::string, std::string> mesh_geom_map; // needed for correct shape key naming - std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map - std::map<COLLADAFW::UniqueId, Object*> uid_object_map; // geom uid-to-object - std::vector<Object*> imported_objects; // list of imported objects - - // this structure is used to assign material indices to polygons - // it holds a portion of Mesh faces and corresponds to a DAE primitive list (<triangles>, <polylist>, etc.) - struct Primitive { - MPoly *mpoly; - unsigned int totpoly; - }; - typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive> > MaterialIdPrimitiveArrayMap; - std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map; // crazy name! - std::multimap<COLLADAFW::UniqueId, COLLADAFW::UniqueId> materials_mapped_to_geom; //< materials that have already been mapped to a geometry. A pair of geom uid and mat uid, one geometry can have several materials - - bool set_poly_indices( - MPoly *mpoly, - MLoop *mloop, - int loop_index, - unsigned int *indices, - int loop_count); - - void set_face_uv( - MLoopUV *mloopuv, - UVDataWrapper &uvs, - int loop_index, - COLLADAFW::IndexList& index_list, - int count); - - void set_vcol( - MLoopCol *mloopcol, - VCOLDataWrapper &vob, - int loop_index, - COLLADAFW::IndexList& index_list, - int count); +class MeshImporter : public MeshImporterBase { + private: + UnitConverter *unitconverter; + + Main *m_bmain; + Scene *scene; + ViewLayer *view_layer; + + ArmatureImporter *armature_importer; + + std::map<std::string, std::string> mesh_geom_map; // needed for correct shape key naming + std::map<COLLADAFW::UniqueId, Mesh *> uid_mesh_map; // geometry unique id-to-mesh map + std::map<COLLADAFW::UniqueId, Object *> uid_object_map; // geom uid-to-object + std::vector<Object *> imported_objects; // list of imported objects + + // this structure is used to assign material indices to polygons + // it holds a portion of Mesh faces and corresponds to a DAE primitive list (<triangles>, <polylist>, etc.) + struct Primitive { + MPoly *mpoly; + unsigned int totpoly; + }; + typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive>> MaterialIdPrimitiveArrayMap; + std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> + geom_uid_mat_mapping_map; // crazy name! + std::multimap<COLLADAFW::UniqueId, COLLADAFW::UniqueId> + materials_mapped_to_geom; //< materials that have already been mapped to a geometry. A pair of geom uid and mat uid, one geometry can have several materials + + bool set_poly_indices( + MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count); + + void set_face_uv(MLoopUV *mloopuv, + UVDataWrapper &uvs, + int loop_index, + COLLADAFW::IndexList &index_list, + int count); + + void set_vcol(MLoopCol *mloopcol, + VCOLDataWrapper &vob, + int loop_index, + COLLADAFW::IndexList &index_list, + int count); #ifdef COLLADA_DEBUG - void print_index_list(COLLADAFW::IndexList& index_list); + void print_index_list(COLLADAFW::IndexList &index_list); #endif - bool is_nice_mesh(COLLADAFW::Mesh *mesh); - - void read_vertices(COLLADAFW::Mesh *mesh, Mesh *me); - - bool primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp); - bool primitive_has_faces(COLLADAFW::MeshPrimitive *mp); + bool is_nice_mesh(COLLADAFW::Mesh *mesh); - static void mesh_add_edges(Mesh *mesh, int len); + void read_vertices(COLLADAFW::Mesh *mesh, Mesh *me); - unsigned int get_loose_edge_count(COLLADAFW::Mesh *mesh); + bool primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp); + bool primitive_has_faces(COLLADAFW::MeshPrimitive *mp); - CustomData create_edge_custom_data(EdgeHash *eh); + static void mesh_add_edges(Mesh *mesh, int len); - void allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me); + unsigned int get_loose_edge_count(COLLADAFW::Mesh *mesh); - // TODO: import uv set names - void read_polys(COLLADAFW::Mesh *mesh, Mesh *me); - void read_lines(COLLADAFW::Mesh *mesh, Mesh *me); - unsigned int get_vertex_count(COLLADAFW::Polygons *mp, int index); + CustomData create_edge_custom_data(EdgeHash *eh); - void get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride); + void allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me); - bool is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count); + // TODO: import uv set names + void read_polys(COLLADAFW::Mesh *mesh, Mesh *me); + void read_lines(COLLADAFW::Mesh *mesh, Mesh *me); + unsigned int get_vertex_count(COLLADAFW::Polygons *mp, int index); - std::vector<Object *> get_all_users_of(Mesh *reference_mesh); + void get_vector(float v[3], COLLADAFW::MeshVertexData &arr, int i, int stride); -public: + bool is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData &nor, int count); - MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer); + std::vector<Object *> get_all_users_of(Mesh *reference_mesh); - virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid); + public: + MeshImporter(UnitConverter *unitconv, + ArmatureImporter *arm, + Main *bmain, + Scene *sce, + ViewLayer *view_layer); - virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& geom_uid); + virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId &geom_uid); - void optimize_material_assignements(); + virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId &geom_uid); - void assign_material_to_geom( - COLLADAFW::MaterialBinding cmaterial, - std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, - Object *ob, const COLLADAFW::UniqueId *geom_uid, - short mat_index); + void optimize_material_assignements(); + void assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, + std::map<COLLADAFW::UniqueId, Material *> &uid_material_map, + Object *ob, + const COLLADAFW::UniqueId *geom_uid, + short mat_index); - Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom, - bool isController, - std::map<COLLADAFW::UniqueId, Material*>& uid_material_map); + Object *create_mesh_object(COLLADAFW::Node *node, + COLLADAFW::InstanceGeometry *geom, + bool isController, + std::map<COLLADAFW::UniqueId, Material *> &uid_material_map); - // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID - bool write_geometry(const COLLADAFW::Geometry* geom); - std::string *get_geometry_name(const std::string &mesh_name); + // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID + bool write_geometry(const COLLADAFW::Geometry *geom); + std::string *get_geometry_name(const std::string &mesh_name); }; #endif diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 9031aa1ed9f..e689cffe470 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -19,10 +19,10 @@ */ extern "C" { - #include "BLI_utildefines.h" - #include "BKE_collection.h" - #include "BKE_object.h" - #include "BLI_listbase.h" +#include "BLI_utildefines.h" +#include "BKE_collection.h" +#include "BKE_object.h" +#include "BLI_listbase.h" } #include "SceneExporter.h" @@ -30,206 +30,210 @@ extern "C" { void SceneExporter::exportScene() { - Scene *scene = blender_context.get_scene(); - - // <library_visual_scenes> <visual_scene> - std::string name = id_name(scene); - openVisualScene(translate_id(name), encode_xml(name)); - exportHierarchy(); - closeVisualScene(); - closeLibrary(); + Scene *scene = blender_context.get_scene(); + + // <library_visual_scenes> <visual_scene> + std::string name = id_name(scene); + openVisualScene(translate_id(name), encode_xml(name)); + exportHierarchy(); + closeVisualScene(); + closeLibrary(); } void SceneExporter::exportHierarchy() { - LinkNode *node; - std::vector<Object *> base_objects; - - // Ensure all objects in the export_set are marked - for (node = this->export_settings->export_set; node; node = node->next) { - Object *ob = (Object *) node->link; - ob->id.tag |= LIB_TAG_DOIT; - } - - // Now find all exportable base objects (highest in export hierarchy) - for (node = this->export_settings->export_set; node; node = node->next) { - Object *ob = (Object *) node->link; - if (bc_is_base_node(this->export_settings->export_set, ob)) { - switch (ob->type) { - case OB_MESH: - case OB_CAMERA: - case OB_LAMP: - case OB_EMPTY: - case OB_GPENCIL: - case OB_ARMATURE: - base_objects.push_back(ob); - break; - } - } - } - - // And now export the base objects: - for (int index = 0; index < base_objects.size(); index++) { - Object *ob = base_objects[index]; - if (bc_is_marked(ob)) { - bc_remove_mark(ob); - writeNodes(ob); - } - } + LinkNode *node; + std::vector<Object *> base_objects; + + // Ensure all objects in the export_set are marked + for (node = this->export_settings->export_set; node; node = node->next) { + Object *ob = (Object *)node->link; + ob->id.tag |= LIB_TAG_DOIT; + } + + // Now find all exportable base objects (highest in export hierarchy) + for (node = this->export_settings->export_set; node; node = node->next) { + Object *ob = (Object *)node->link; + if (bc_is_base_node(this->export_settings->export_set, ob)) { + switch (ob->type) { + case OB_MESH: + case OB_CAMERA: + case OB_LAMP: + case OB_EMPTY: + case OB_GPENCIL: + case OB_ARMATURE: + base_objects.push_back(ob); + break; + } + } + } + + // And now export the base objects: + for (int index = 0; index < base_objects.size(); index++) { + Object *ob = base_objects[index]; + if (bc_is_marked(ob)) { + bc_remove_mark(ob); + writeNodes(ob); + } + } } void SceneExporter::writeNodeList(std::vector<Object *> &child_objects, Object *parent) { - /* TODO: Handle the case where a parent is not exported - Actually i am not even sure if this can be done at all - in a good way. - I really prefer to enforce the export of hidden - elements in an object hierarchy. When the children of - the hidden elements are exported as well. - */ - for (int i = 0; i < child_objects.size(); ++i) { - Object *child = child_objects[i]; - if (bc_is_marked(child)) { - bc_remove_mark(child); - writeNodes(child); - } - } + /* TODO: Handle the case where a parent is not exported + Actually i am not even sure if this can be done at all + in a good way. + I really prefer to enforce the export of hidden + elements in an object hierarchy. When the children of + the hidden elements are exported as well. + */ + for (int i = 0; i < child_objects.size(); ++i) { + Object *child = child_objects[i]; + if (bc_is_marked(child)) { + bc_remove_mark(child); + writeNodes(child); + } + } } void SceneExporter::writeNodes(Object *ob) { - ViewLayer *view_layer = blender_context.get_view_layer(); - - std::vector<Object *> child_objects; - bc_get_children(child_objects, ob, view_layer); - bool can_export = bc_is_in_Export_set(this->export_settings->export_set, ob, view_layer); - - // Add associated armature first if available - bool armature_exported = false; - Object *ob_arm = bc_get_assigned_armature(ob); - - if (ob_arm != NULL) { - armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm, view_layer); - if (armature_exported && bc_is_marked(ob_arm)) { - bc_remove_mark(ob_arm); - writeNodes(ob_arm); - armature_exported = true; - } - } - - if (can_export) { - COLLADASW::Node colladaNode(mSW); - colladaNode.setNodeId(translate_id(id_name(ob))); - colladaNode.setNodeName(encode_xml(id_name(ob))); - colladaNode.setType(COLLADASW::Node::NODE); - - colladaNode.start(); - - if (ob->type == OB_MESH && armature_exported) { - // for skinned mesh we write obmat in <bind_shape_matrix> - TransformWriter::add_node_transform_identity(colladaNode); - } - else { - TransformWriter::add_node_transform_ob( - colladaNode, - ob, - this->export_settings->export_transformation_type, - this->export_settings->limit_precision - ); - } - - // <instance_geometry> - if (ob->type == OB_MESH) { - bool instance_controller_created = false; - if (armature_exported) { - instance_controller_created = arm_exporter->add_instance_controller(ob); - } - if (!instance_controller_created) { - COLLADASW::InstanceGeometry instGeom(mSW); - instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); - instGeom.setName(encode_xml(id_name(ob))); - InstanceWriter::add_material_bindings( - instGeom.getBindMaterial(), - ob, - this->export_settings->active_uv_only); - instGeom.add(); - } - } - - // <instance_controller> - else if (ob->type == OB_ARMATURE) { - arm_exporter->add_armature_bones(ob, view_layer, this, child_objects); - } - - // <instance_camera> - else if (ob->type == OB_CAMERA) { - COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob))); - instCam.add(); - } - - // <instance_light> - else if (ob->type == OB_LAMP) { - COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob))); - instLa.add(); - } - - // empty object - else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLICOLLECTION - if ((ob->transflag & OB_DUPLICOLLECTION) == OB_DUPLICOLLECTION && ob->instance_collection) { - Collection *collection = ob->instance_collection; - /* printf("group detected '%s'\n", group->id.name + 2); */ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object) - { - printf("\t%s\n", object->id.name); - } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - } - - if (BLI_listbase_is_empty(&ob->constraints) == false) { - bConstraint *con = (bConstraint *)ob->constraints.first; - while (con) { - std::string con_name(encode_xml(con->name)); - std::string con_tag = con_name + "_constraint"; - printf("%s\n", con_name.c_str()); - printf("%s\n\n", con_tag.c_str()); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "type", con->type); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "enforce", con->enforce); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "flag", con->flag); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "headtail", con->headtail); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "lin_error", con->lin_error); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "own_space", con->ownspace); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "rot_error", con->rot_error); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "tar_space", con->tarspace); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "lin_error", con->lin_error); - - //not ideal: add the target object name as another parameter. - //No real mapping in the .dae - //Need support for multiple target objects also. - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - ListBase targets = { NULL, NULL }; - if (cti && cti->get_constraint_targets) { - - bConstraintTarget *ct; - Object *obtar; - - cti->get_constraint_targets(con, &targets); - - for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { - obtar = ct->tar; - std::string tar_id((obtar) ? id_name(obtar) : ""); - colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "target_id", tar_id); - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 1); - - } - - con = con->next; - } - } - } - writeNodeList(child_objects, ob); - colladaNode.end(); - } + ViewLayer *view_layer = blender_context.get_view_layer(); + + std::vector<Object *> child_objects; + bc_get_children(child_objects, ob, view_layer); + bool can_export = bc_is_in_Export_set(this->export_settings->export_set, ob, view_layer); + + // Add associated armature first if available + bool armature_exported = false; + Object *ob_arm = bc_get_assigned_armature(ob); + + if (ob_arm != NULL) { + armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm, view_layer); + if (armature_exported && bc_is_marked(ob_arm)) { + bc_remove_mark(ob_arm); + writeNodes(ob_arm); + armature_exported = true; + } + } + + if (can_export) { + COLLADASW::Node colladaNode(mSW); + colladaNode.setNodeId(translate_id(id_name(ob))); + colladaNode.setNodeName(encode_xml(id_name(ob))); + colladaNode.setType(COLLADASW::Node::NODE); + + colladaNode.start(); + + if (ob->type == OB_MESH && armature_exported) { + // for skinned mesh we write obmat in <bind_shape_matrix> + TransformWriter::add_node_transform_identity(colladaNode); + } + else { + TransformWriter::add_node_transform_ob(colladaNode, + ob, + this->export_settings->export_transformation_type, + this->export_settings->limit_precision); + } + + // <instance_geometry> + if (ob->type == OB_MESH) { + bool instance_controller_created = false; + if (armature_exported) { + instance_controller_created = arm_exporter->add_instance_controller(ob); + } + if (!instance_controller_created) { + COLLADASW::InstanceGeometry instGeom(mSW); + instGeom.setUrl( + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, + get_geometry_id(ob, this->export_settings->use_object_instantiation))); + instGeom.setName(encode_xml(id_name(ob))); + InstanceWriter::add_material_bindings( + instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only); + instGeom.add(); + } + } + + // <instance_controller> + else if (ob->type == OB_ARMATURE) { + arm_exporter->add_armature_bones(ob, view_layer, this, child_objects); + } + + // <instance_camera> + else if (ob->type == OB_CAMERA) { + COLLADASW::InstanceCamera instCam( + mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob))); + instCam.add(); + } + + // <instance_light> + else if (ob->type == OB_LAMP) { + COLLADASW::InstanceLight instLa( + mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob))); + instLa.add(); + } + + // empty object + else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLICOLLECTION + if ((ob->transflag & OB_DUPLICOLLECTION) == OB_DUPLICOLLECTION && ob->instance_collection) { + Collection *collection = ob->instance_collection; + /* printf("group detected '%s'\n", group->id.name + 2); */ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, object) { + printf("\t%s\n", object->id.name); + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } + + if (BLI_listbase_is_empty(&ob->constraints) == false) { + bConstraint *con = (bConstraint *)ob->constraints.first; + while (con) { + std::string con_name(encode_xml(con->name)); + std::string con_tag = con_name + "_constraint"; + printf("%s\n", con_name.c_str()); + printf("%s\n\n", con_tag.c_str()); + colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "type", con->type); + colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "enforce", con->enforce); + colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "flag", con->flag); + colladaNode.addExtraTechniqueChildParameter( + "blender", con_tag, "headtail", con->headtail); + colladaNode.addExtraTechniqueChildParameter( + "blender", con_tag, "lin_error", con->lin_error); + colladaNode.addExtraTechniqueChildParameter( + "blender", con_tag, "own_space", con->ownspace); + colladaNode.addExtraTechniqueChildParameter( + "blender", con_tag, "rot_error", con->rot_error); + colladaNode.addExtraTechniqueChildParameter( + "blender", con_tag, "tar_space", con->tarspace); + colladaNode.addExtraTechniqueChildParameter( + "blender", con_tag, "lin_error", con->lin_error); + + //not ideal: add the target object name as another parameter. + //No real mapping in the .dae + //Need support for multiple target objects also. + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + ListBase targets = {NULL, NULL}; + if (cti && cti->get_constraint_targets) { + + bConstraintTarget *ct; + Object *obtar; + + cti->get_constraint_targets(con, &targets); + + for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { + obtar = ct->tar; + std::string tar_id((obtar) ? id_name(obtar) : ""); + colladaNode.addExtraTechniqueChildParameter("blender", con_tag, "target_id", tar_id); + } + + if (cti->flush_constraint_targets) + cti->flush_constraint_targets(con, &targets, 1); + } + + con = con->next; + } + } + } + writeNodeList(child_objects, ob); + colladaNode.end(); + } } diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h index 033616ac0a4..dc0a0c3e2ad 100644 --- a/source/blender/collada/SceneExporter.h +++ b/source/blender/collada/SceneExporter.h @@ -85,29 +85,32 @@ extern "C" { #include "ExportSettings.h" -class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter -{ -public: +class SceneExporter : COLLADASW::LibraryVisualScenes, + protected TransformWriter, + protected InstanceWriter { + public: + SceneExporter(BlenderContext &blender_context, + COLLADASW::StreamWriter *sw, + ArmatureExporter *arm, + const ExportSettings *export_settings) + : COLLADASW::LibraryVisualScenes(sw), + blender_context(blender_context), + arm_exporter(arm), + export_settings(export_settings) + { + } - SceneExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings) : - COLLADASW::LibraryVisualScenes(sw), - blender_context(blender_context), - arm_exporter(arm), - export_settings(export_settings) - {} + void exportScene(); - void exportScene(); - -private: - BlenderContext &blender_context; - friend class ArmatureExporter; - ArmatureExporter *arm_exporter; - const ExportSettings *export_settings; - - void exportHierarchy(); - void writeNodeList(std::vector<Object *> &child_objects, Object *parent); - void writeNodes(Object *ob); + private: + BlenderContext &blender_context; + friend class ArmatureExporter; + ArmatureExporter *arm_exporter; + const ExportSettings *export_settings; + void exportHierarchy(); + void writeNodeList(std::vector<Object *> &child_objects, Object *parent); + void writeNodes(Object *ob); }; #endif diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp index 337fa94f476..d0f2e2d6332 100644 --- a/source/blender/collada/SkinInfo.cpp +++ b/source/blender/collada/SkinInfo.cpp @@ -18,11 +18,10 @@ * \ingroup collada */ - #include <algorithm> #if !defined(WIN32) -#include <stdint.h> +# include <stdint.h> #endif /* COLLADABU_ASSERT, may be able to remove later */ @@ -47,11 +46,10 @@ #include "collada_utils.h" // use name, or fall back to original id if name not present (name is optional) -template<class T> -static const char *bc_get_joint_name(T *node) +template<class T> static const char *bc_get_joint_name(T *node) { - const std::string& id = node->getName(); - return id.size() ? id.c_str() : node->getOriginalId().c_str(); + const std::string &id = node->getName(); + return id.size() ? id.c_str() : node->getOriginalId().c_str(); } // This is used to store data passed in write_controller_data. @@ -59,137 +57,140 @@ static const char *bc_get_joint_name(T *node) // so that arrays don't get freed until we free them explicitly. SkinInfo::SkinInfo() { - /* pass */ + /* pass */ } -SkinInfo::SkinInfo(const SkinInfo& skin) : weights(skin.weights), - joint_data(skin.joint_data), - unit_converter(skin.unit_converter), - ob_arm(skin.ob_arm), - controller_uid(skin.controller_uid), - parent(skin.parent) +SkinInfo::SkinInfo(const SkinInfo &skin) + : weights(skin.weights), + joint_data(skin.joint_data), + unit_converter(skin.unit_converter), + ob_arm(skin.ob_arm), + controller_uid(skin.controller_uid), + parent(skin.parent) { - copy_m4_m4(bind_shape_matrix, (float (*)[4])skin.bind_shape_matrix); + copy_m4_m4(bind_shape_matrix, (float(*)[4])skin.bind_shape_matrix); - transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex); - transfer_uint_array_data_const(skin.weight_indices, weight_indices); - transfer_int_array_data_const(skin.joint_indices, joint_indices); + transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex); + transfer_uint_array_data_const(skin.weight_indices, weight_indices); + transfer_int_array_data_const(skin.joint_indices, joint_indices); } -SkinInfo::SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL), parent(NULL) { +SkinInfo::SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL), parent(NULL) +{ } // nobody owns the data after this, so it should be freed manually with releaseMemory -template <class T> -void SkinInfo::transfer_array_data(T& src, T& dest) +template<class T> void SkinInfo::transfer_array_data(T &src, T &dest) { - dest.setData(src.getData(), src.getCount()); - src.yieldOwnerShip(); - dest.yieldOwnerShip(); + dest.setData(src.getData(), src.getCount()); + src.yieldOwnerShip(); + dest.yieldOwnerShip(); } // when src is const we cannot src.yieldOwnerShip, this is used by copy constructor -void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray& src, COLLADAFW::IntValuesArray& dest) +void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray &src, + COLLADAFW::IntValuesArray &dest) { - dest.setData((int *)src.getData(), src.getCount()); - dest.yieldOwnerShip(); + dest.setData((int *)src.getData(), src.getCount()); + dest.yieldOwnerShip(); } -void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray& src, COLLADAFW::UIntValuesArray& dest) +void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray &src, + COLLADAFW::UIntValuesArray &dest) { - dest.setData((unsigned int *)src.getData(), src.getCount()); - dest.yieldOwnerShip(); + dest.setData((unsigned int *)src.getData(), src.getCount()); + dest.yieldOwnerShip(); } void SkinInfo::borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin) { - transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getJointsPerVertex(), joints_per_vertex); - transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getWeightIndices(), weight_indices); - transfer_array_data((COLLADAFW::IntValuesArray &)skin->getJointIndices(), joint_indices); - // transfer_array_data(skin->getWeights(), weights); + transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getJointsPerVertex(), joints_per_vertex); + transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getWeightIndices(), weight_indices); + transfer_array_data((COLLADAFW::IntValuesArray &)skin->getJointIndices(), joint_indices); + // transfer_array_data(skin->getWeights(), weights); - // cannot transfer data for FloatOrDoubleArray, copy values manually - const COLLADAFW::FloatOrDoubleArray& weight = skin->getWeights(); - for (unsigned int i = 0; i < weight.getValuesCount(); i++) - weights.push_back(bc_get_float_value(weight, i)); + // cannot transfer data for FloatOrDoubleArray, copy values manually + const COLLADAFW::FloatOrDoubleArray &weight = skin->getWeights(); + for (unsigned int i = 0; i < weight.getValuesCount(); i++) + weights.push_back(bc_get_float_value(weight, i)); - unit_converter->dae_matrix_to_mat4_(bind_shape_matrix, skin->getBindShapeMatrix()); + unit_converter->dae_matrix_to_mat4_(bind_shape_matrix, skin->getBindShapeMatrix()); } void SkinInfo::free() { - joints_per_vertex.releaseMemory(); - weight_indices.releaseMemory(); - joint_indices.releaseMemory(); - // weights.releaseMemory(); + joints_per_vertex.releaseMemory(); + weight_indices.releaseMemory(); + joint_indices.releaseMemory(); + // weights.releaseMemory(); } // using inverse bind matrices to construct armature // it is safe to invert them to get the original matrices // because if they are inverse matrices, they can be inverted -void SkinInfo::add_joint(const COLLADABU::Math::Matrix4& matrix) +void SkinInfo::add_joint(const COLLADABU::Math::Matrix4 &matrix) { - JointData jd; - unit_converter->dae_matrix_to_mat4_(jd.inv_bind_mat, matrix); - joint_data.push_back(jd); + JointData jd; + unit_converter->dae_matrix_to_mat4_(jd.inv_bind_mat, matrix); + joint_data.push_back(jd); } void SkinInfo::set_controller(const COLLADAFW::SkinController *co) { - controller_uid = co->getUniqueId(); + controller_uid = co->getUniqueId(); - // fill in joint UIDs - const COLLADAFW::UniqueIdArray& joint_uids = co->getJoints(); - for (unsigned int i = 0; i < joint_uids.getCount(); i++) { - joint_data[i].joint_uid = joint_uids[i]; + // fill in joint UIDs + const COLLADAFW::UniqueIdArray &joint_uids = co->getJoints(); + for (unsigned int i = 0; i < joint_uids.getCount(); i++) { + joint_data[i].joint_uid = joint_uids[i]; - // // store armature pointer - // JointData& jd = joint_index_to_joint_info_map[i]; - // jd.ob_arm = ob_arm; + // // store armature pointer + // JointData& jd = joint_index_to_joint_info_map[i]; + // jd.ob_arm = ob_arm; - // now we'll be able to get inv bind matrix from joint id - // joint_id_to_joint_index_map[joint_ids[i]] = i; - } + // now we'll be able to get inv bind matrix from joint id + // joint_id_to_joint_index_map[joint_ids[i]] = i; + } } // called from write_controller Object *SkinInfo::create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer) { - ob_arm = bc_add_object(bmain, scene, view_layer, OB_ARMATURE, NULL); - return ob_arm; + ob_arm = bc_add_object(bmain, scene, view_layer, OB_ARMATURE, NULL); + return ob_arm; } Object *SkinInfo::set_armature(Object *ob_arm) { - if (this->ob_arm) - return this->ob_arm; + if (this->ob_arm) + return this->ob_arm; - this->ob_arm = ob_arm; - return ob_arm; + this->ob_arm = ob_arm; + return ob_arm; } bool SkinInfo::get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node) { - const COLLADAFW::UniqueId& uid = node->getUniqueId(); - std::vector<JointData>::iterator it; - for (it = joint_data.begin(); it != joint_data.end(); it++) { - if ((*it).joint_uid == uid) { - copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat); - return true; - } - } - - return false; + const COLLADAFW::UniqueId &uid = node->getUniqueId(); + std::vector<JointData>::iterator it; + for (it = joint_data.begin(); it != joint_data.end(); it++) { + if ((*it).joint_uid == uid) { + copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat); + return true; + } + } + + return false; } Object *SkinInfo::BKE_armature_from_object() { - return ob_arm; + return ob_arm; } -const COLLADAFW::UniqueId& SkinInfo::get_controller_uid() +const COLLADAFW::UniqueId &SkinInfo::get_controller_uid() { - return controller_uid; + return controller_uid; } // check if this skin controller references a joint or any descendant of it @@ -199,147 +200,150 @@ const COLLADAFW::UniqueId& SkinInfo::get_controller_uid() // we need to search down the tree bool SkinInfo::uses_joint_or_descendant(COLLADAFW::Node *node) { - const COLLADAFW::UniqueId& uid = node->getUniqueId(); - std::vector<JointData>::iterator it; - for (it = joint_data.begin(); it != joint_data.end(); it++) { - if ((*it).joint_uid == uid) - return true; - } - - COLLADAFW::NodePointerArray& children = node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { - if (uses_joint_or_descendant(children[i])) - return true; - } - - return false; + const COLLADAFW::UniqueId &uid = node->getUniqueId(); + std::vector<JointData>::iterator it; + for (it = joint_data.begin(); it != joint_data.end(); it++) { + if ((*it).joint_uid == uid) + return true; + } + + COLLADAFW::NodePointerArray &children = node->getChildNodes(); + for (unsigned int i = 0; i < children.getCount(); i++) { + if (uses_joint_or_descendant(children[i])) + return true; + } + + return false; } -void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& joint_by_uid, +void SkinInfo::link_armature(bContext *C, + Object *ob, + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid, TransformReader *tm) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); - ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature); - ArmatureModifierData *amd = (ArmatureModifierData *)md; - amd->object = ob_arm; + ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature); + ArmatureModifierData *amd = (ArmatureModifierData *)md; + amd->object = ob_arm; #if 1 - /* XXX Why do we enforce objects to be children of Armatures if they weren't so before ?*/ - if (!BKE_object_is_child_recursive(ob_arm, ob)) { - bc_set_parent(ob, ob_arm, C); - } + /* XXX Why do we enforce objects to be children of Armatures if they weren't so before ?*/ + if (!BKE_object_is_child_recursive(ob_arm, ob)) { + bc_set_parent(ob, ob_arm, C); + } #else - Object workob; - ob->parent = ob_arm; - ob->partype = PAROBJECT; + Object workob; + ob->parent = ob_arm; + ob->partype = PAROBJECT; - BKE_object_workob_calc_parent(scene, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + BKE_object_workob_calc_parent(scene, ob, &workob); + invert_m4_m4(ob->parentinv, workob.obmat); - DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); #endif - copy_m4_m4(ob->obmat, bind_shape_matrix); - BKE_object_apply_mat4(ob, ob->obmat, 0, 0); + copy_m4_m4(ob->obmat, bind_shape_matrix); + BKE_object_apply_mat4(ob, ob->obmat, 0, 0); - amd->deformflag = ARM_DEF_VGROUP; + amd->deformflag = ARM_DEF_VGROUP; - // create all vertex groups - std::vector<JointData>::iterator it; - int joint_index; - for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) { - const char *name = "Group"; + // create all vertex groups + std::vector<JointData>::iterator it; + int joint_index; + for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) { + const char *name = "Group"; - // skip joints that have invalid UID - if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue; + // skip joints that have invalid UID + if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) + continue; - // name group by joint node name + // name group by joint node name - if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) { - name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]); - } + if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) { + name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]); + } - BKE_object_defgroup_add_name(ob, name); - } + BKE_object_defgroup_add_name(ob, name); + } - // <vcount> - number of joints per vertex - joints_per_vertex - // <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices - // ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender? + // <vcount> - number of joints per vertex - joints_per_vertex + // <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices + // ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender? - // for each vertex in weight indices - // for each bone index in vertex - // add vertex to group at group index - // treat group index -1 specially + // for each vertex in weight indices + // for each bone index in vertex + // add vertex to group at group index + // treat group index -1 specially - // get def group by index with BLI_findlink + // get def group by index with BLI_findlink - for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) { + for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) { - unsigned int limit = weight + joints_per_vertex[vertex]; - for (; weight < limit; weight++) { - int joint = joint_indices[weight], joint_weight = weight_indices[weight]; + unsigned int limit = weight + joints_per_vertex[vertex]; + for (; weight < limit; weight++) { + int joint = joint_indices[weight], joint_weight = weight_indices[weight]; - // -1 means "weight towards the bind shape", we just don't assign it to any group - if (joint != -1) { - bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint); + // -1 means "weight towards the bind shape", we just don't assign it to any group + if (joint != -1) { + bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint); - ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE); - } - } - } + ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE); + } + } + } } bPoseChannel *SkinInfo::get_pose_channel_from_node(COLLADAFW::Node *node) { - return BKE_pose_channel_find_name(ob_arm->pose, bc_get_joint_name(node)); + return BKE_pose_channel_find_name(ob_arm->pose, bc_get_joint_name(node)); } void SkinInfo::set_parent(Object *_parent) { - parent = _parent; + parent = _parent; } Object *SkinInfo::get_parent() { - return parent; + return parent; } void SkinInfo::find_root_joints(const std::vector<COLLADAFW::Node *> &root_joints, - std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& joint_by_uid, - std::vector<COLLADAFW::Node *>& result) + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid, + std::vector<COLLADAFW::Node *> &result) { - std::vector<COLLADAFW::Node *>::const_iterator it; - // for each root_joint - for (it = root_joints.begin(); it != root_joints.end(); it++) { - COLLADAFW::Node *root = *it; - std::vector<JointData>::iterator ji; - //for each joint_data in this skin - for (ji = joint_data.begin(); ji != joint_data.end(); ji++) { - if (joint_by_uid.find((*ji).joint_uid) != joint_by_uid.end()) { - //get joint node from joint map - COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid]; - - //find if joint node is in the tree belonging to the root_joint - if (find_node_in_tree(joint, root)) { - if (std::find(result.begin(), result.end(), root) == result.end()) - result.push_back(root); - } - } - } - } + std::vector<COLLADAFW::Node *>::const_iterator it; + // for each root_joint + for (it = root_joints.begin(); it != root_joints.end(); it++) { + COLLADAFW::Node *root = *it; + std::vector<JointData>::iterator ji; + //for each joint_data in this skin + for (ji = joint_data.begin(); ji != joint_data.end(); ji++) { + if (joint_by_uid.find((*ji).joint_uid) != joint_by_uid.end()) { + //get joint node from joint map + COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid]; + + //find if joint node is in the tree belonging to the root_joint + if (find_node_in_tree(joint, root)) { + if (std::find(result.begin(), result.end(), root) == result.end()) + result.push_back(root); + } + } + } + } } bool SkinInfo::find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root) { - if (node == tree_root) - return true; + if (node == tree_root) + return true; - COLLADAFW::NodePointerArray& children = tree_root->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { - if (find_node_in_tree(node, children[i])) - return true; - } + COLLADAFW::NodePointerArray &children = tree_root->getChildNodes(); + for (unsigned int i = 0; i < children.getCount(); i++) { + if (find_node_in_tree(node, children[i])) + return true; + } - return false; + return false; } diff --git a/source/blender/collada/SkinInfo.h b/source/blender/collada/SkinInfo.h index 7695547f9b5..255d6d9b1f3 100644 --- a/source/blender/collada/SkinInfo.h +++ b/source/blender/collada/SkinInfo.h @@ -39,91 +39,92 @@ // This is used to store data passed in write_controller_data. // Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members // so that arrays don't get freed until we free them explicitly. -class SkinInfo -{ -private: - // to build armature bones from inverse bind matrices - struct JointData { - float inv_bind_mat[4][4]; // joint inverse bind matrix - COLLADAFW::UniqueId joint_uid; // joint node UID - // Object *ob_arm; // armature object - }; +class SkinInfo { + private: + // to build armature bones from inverse bind matrices + struct JointData { + float inv_bind_mat[4][4]; // joint inverse bind matrix + COLLADAFW::UniqueId joint_uid; // joint node UID + // Object *ob_arm; // armature object + }; - float bind_shape_matrix[4][4]; + float bind_shape_matrix[4][4]; - // data from COLLADAFW::SkinControllerData, each array should be freed - COLLADAFW::UIntValuesArray joints_per_vertex; - COLLADAFW::UIntValuesArray weight_indices; - COLLADAFW::IntValuesArray joint_indices; - // COLLADAFW::FloatOrDoubleArray weights; - std::vector<float> weights; + // data from COLLADAFW::SkinControllerData, each array should be freed + COLLADAFW::UIntValuesArray joints_per_vertex; + COLLADAFW::UIntValuesArray weight_indices; + COLLADAFW::IntValuesArray joint_indices; + // COLLADAFW::FloatOrDoubleArray weights; + std::vector<float> weights; - std::vector<JointData> joint_data; // index to this vector is joint index + std::vector<JointData> joint_data; // index to this vector is joint index - UnitConverter *unit_converter; + UnitConverter *unit_converter; - Object *ob_arm; - COLLADAFW::UniqueId controller_uid; - Object *parent; + Object *ob_arm; + COLLADAFW::UniqueId controller_uid; + Object *parent; -public: + public: + SkinInfo(); + SkinInfo(const SkinInfo &skin); + SkinInfo(UnitConverter *conv); - SkinInfo(); - SkinInfo(const SkinInfo& skin); - SkinInfo(UnitConverter *conv); + // nobody owns the data after this, so it should be freed manually with releaseMemory + template<typename T> void transfer_array_data(T &src, T &dest); - // nobody owns the data after this, so it should be freed manually with releaseMemory - template <typename T> - void transfer_array_data(T& src, T& dest); + // when src is const we cannot src.yieldOwnerShip, this is used by copy constructor + void transfer_int_array_data_const(const COLLADAFW::IntValuesArray &src, + COLLADAFW::IntValuesArray &dest); - // when src is const we cannot src.yieldOwnerShip, this is used by copy constructor - void transfer_int_array_data_const(const COLLADAFW::IntValuesArray& src, COLLADAFW::IntValuesArray& dest); + void transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray &src, + COLLADAFW::UIntValuesArray &dest); - void transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray& src, COLLADAFW::UIntValuesArray& dest); + void borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin); - void borrow_skin_controller_data(const COLLADAFW::SkinControllerData* skin); + void free(); - void free(); + // using inverse bind matrices to construct armature + // it is safe to invert them to get the original matrices + // because if they are inverse matrices, they can be inverted + void add_joint(const COLLADABU::Math::Matrix4 &matrix); - // using inverse bind matrices to construct armature - // it is safe to invert them to get the original matrices - // because if they are inverse matrices, they can be inverted - void add_joint(const COLLADABU::Math::Matrix4& matrix); + void set_controller(const COLLADAFW::SkinController *co); - void set_controller(const COLLADAFW::SkinController* co); + // called from write_controller + Object *create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer); - // called from write_controller - Object *create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer); + Object *set_armature(Object *ob_arm); - Object* set_armature(Object *ob_arm); + bool get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node); - bool get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node); + Object *BKE_armature_from_object(); - Object *BKE_armature_from_object(); + const COLLADAFW::UniqueId &get_controller_uid(); - const COLLADAFW::UniqueId& get_controller_uid(); + // check if this skin controller references a joint or any descendant of it + // + // some nodes may not be referenced by SkinController, + // in this case to determine if the node belongs to this armature, + // we need to search down the tree + bool uses_joint_or_descendant(COLLADAFW::Node *node); - // check if this skin controller references a joint or any descendant of it - // - // some nodes may not be referenced by SkinController, - // in this case to determine if the node belongs to this armature, - // we need to search down the tree - bool uses_joint_or_descendant(COLLADAFW::Node *node); + void link_armature(bContext *C, + Object *ob, + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid, + TransformReader *tm); - void link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid, TransformReader *tm); + bPoseChannel *get_pose_channel_from_node(COLLADAFW::Node *node); - bPoseChannel *get_pose_channel_from_node(COLLADAFW::Node *node); + void set_parent(Object *_parent); - void set_parent(Object *_parent); + Object *get_parent(); - Object* get_parent(); - - void find_root_joints(const std::vector<COLLADAFW::Node*> &root_joints, - std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid, - std::vector<COLLADAFW::Node*>& result); - - bool find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root); + void find_root_joints(const std::vector<COLLADAFW::Node *> &root_joints, + std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid, + std::vector<COLLADAFW::Node *> &result); + bool find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root); }; #endif diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp index 6a557ea8120..8ee31f80405 100644 --- a/source/blender/collada/TransformReader.cpp +++ b/source/blender/collada/TransformReader.cpp @@ -25,129 +25,127 @@ TransformReader::TransformReader(UnitConverter *conv) : unit_converter(conv) { - /* pass */ + /* pass */ } -void TransformReader::get_node_mat( - float mat[4][4], - COLLADAFW::Node *node, - std::map<COLLADAFW::UniqueId, Animation> *animation_map, - Object *ob) +void TransformReader::get_node_mat(float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob) { - get_node_mat(mat, node, animation_map, ob, NULL); + get_node_mat(mat, node, animation_map, ob, NULL); } -void TransformReader::get_node_mat( - float mat[4][4], - COLLADAFW::Node *node, - std::map<COLLADAFW::UniqueId, Animation> *animation_map, - Object *ob, - float parent_mat[4][4]) +void TransformReader::get_node_mat(float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob, + float parent_mat[4][4]) { - float cur[4][4]; - float copy[4][4]; - - unit_m4(mat); - - for (unsigned int i = 0; i < node->getTransformations().getCount(); i++) { - - COLLADAFW::Transformation *tm = node->getTransformations()[i]; - COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); - - switch (type) { - case COLLADAFW::Transformation::MATRIX: - // When matrix AND Trans/Rot/Scale are defined for a node, - // then this is considered as redundant information. - // So if we find a Matrix we use that and return. - dae_matrix_to_mat4(tm, mat); - if (parent_mat) { - mul_m4_m4m4(mat, parent_mat, mat); - } - return; - case COLLADAFW::Transformation::TRANSLATE: - dae_translate_to_mat4(tm, cur); - break; - case COLLADAFW::Transformation::ROTATE: - dae_rotate_to_mat4(tm, cur); - break; - case COLLADAFW::Transformation::SCALE: - dae_scale_to_mat4(tm, cur); - break; - case COLLADAFW::Transformation::LOOKAT: - fprintf(stderr, "|! LOOKAT transformations are not supported yet.\n"); - break; - case COLLADAFW::Transformation::SKEW: - fprintf(stderr, "|! SKEW transformations are not supported yet.\n"); - break; - } - - copy_m4_m4(copy, mat); - mul_m4_m4m4(mat, copy, cur); - - if (animation_map) { - // AnimationList that drives this Transformation - const COLLADAFW::UniqueId& anim_list_id = tm->getAnimationList(); - - // store this so later we can link animation data with ob - Animation anim = {ob, node, tm}; - (*animation_map)[anim_list_id] = anim; - } - } - - if (parent_mat) { - mul_m4_m4m4(mat, parent_mat, mat); - } + float cur[4][4]; + float copy[4][4]; + + unit_m4(mat); + + for (unsigned int i = 0; i < node->getTransformations().getCount(); i++) { + + COLLADAFW::Transformation *tm = node->getTransformations()[i]; + COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); + + switch (type) { + case COLLADAFW::Transformation::MATRIX: + // When matrix AND Trans/Rot/Scale are defined for a node, + // then this is considered as redundant information. + // So if we find a Matrix we use that and return. + dae_matrix_to_mat4(tm, mat); + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } + return; + case COLLADAFW::Transformation::TRANSLATE: + dae_translate_to_mat4(tm, cur); + break; + case COLLADAFW::Transformation::ROTATE: + dae_rotate_to_mat4(tm, cur); + break; + case COLLADAFW::Transformation::SCALE: + dae_scale_to_mat4(tm, cur); + break; + case COLLADAFW::Transformation::LOOKAT: + fprintf(stderr, "|! LOOKAT transformations are not supported yet.\n"); + break; + case COLLADAFW::Transformation::SKEW: + fprintf(stderr, "|! SKEW transformations are not supported yet.\n"); + break; + } + + copy_m4_m4(copy, mat); + mul_m4_m4m4(mat, copy, cur); + + if (animation_map) { + // AnimationList that drives this Transformation + const COLLADAFW::UniqueId &anim_list_id = tm->getAnimationList(); + + // store this so later we can link animation data with ob + Animation anim = {ob, node, tm}; + (*animation_map)[anim_list_id] = anim; + } + } + + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } } void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) { - COLLADAFW::Rotate *ro = (COLLADAFW::Rotate *)tm; - COLLADABU::Math::Vector3& axis = ro->getRotationAxis(); - const float angle = (float)DEG2RAD(ro->getRotationAngle()); - const float ax[] = {(float)axis[0], (float)axis[1], (float)axis[2]}; - // float quat[4]; - // axis_angle_to_quat(quat, axis, angle); - // quat_to_mat4(m, quat); - axis_angle_to_mat4(m, ax, angle); + COLLADAFW::Rotate *ro = (COLLADAFW::Rotate *)tm; + COLLADABU::Math::Vector3 &axis = ro->getRotationAxis(); + const float angle = (float)DEG2RAD(ro->getRotationAngle()); + const float ax[] = {(float)axis[0], (float)axis[1], (float)axis[2]}; + // float quat[4]; + // axis_angle_to_quat(quat, axis, angle); + // quat_to_mat4(m, quat); + axis_angle_to_mat4(m, ax, angle); } void TransformReader::dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) { - COLLADAFW::Translate *tra = (COLLADAFW::Translate *)tm; - COLLADABU::Math::Vector3& t = tra->getTranslation(); + COLLADAFW::Translate *tra = (COLLADAFW::Translate *)tm; + COLLADABU::Math::Vector3 &t = tra->getTranslation(); - unit_m4(m); + unit_m4(m); - m[3][0] = (float)t[0]; - m[3][1] = (float)t[1]; - m[3][2] = (float)t[2]; + m[3][0] = (float)t[0]; + m[3][1] = (float)t[1]; + m[3][2] = (float)t[2]; } void TransformReader::dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) { - COLLADABU::Math::Vector3& s = ((COLLADAFW::Scale *)tm)->getScale(); - float size[3] = {(float)s[0], (float)s[1], (float)s[2]}; - size_to_mat4(m, size); + COLLADABU::Math::Vector3 &s = ((COLLADAFW::Scale *)tm)->getScale(); + float size[3] = {(float)s[0], (float)s[1], (float)s[2]}; + size_to_mat4(m, size); } void TransformReader::dae_matrix_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) { - unit_converter->dae_matrix_to_mat4_(m, ((COLLADAFW::Matrix *)tm)->getMatrix()); + unit_converter->dae_matrix_to_mat4_(m, ((COLLADAFW::Matrix *)tm)->getMatrix()); } void TransformReader::dae_translate_to_v3(COLLADAFW::Transformation *tm, float v[3]) { - dae_vector3_to_v3(((COLLADAFW::Translate *)tm)->getTranslation(), v); + dae_vector3_to_v3(((COLLADAFW::Translate *)tm)->getTranslation(), v); } void TransformReader::dae_scale_to_v3(COLLADAFW::Transformation *tm, float v[3]) { - dae_vector3_to_v3(((COLLADAFW::Scale *)tm)->getScale(), v); + dae_vector3_to_v3(((COLLADAFW::Scale *)tm)->getScale(), v); } void TransformReader::dae_vector3_to_v3(const COLLADABU::Math::Vector3 &v3, float v[3]) { - v[0] = v3.x; - v[1] = v3.y; - v[2] = v3.z; + v[0] = v3.x; + v[1] = v3.y; + v[2] = v3.z; } diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h index 36d994c9487..6add2950c06 100644 --- a/source/blender/collada/TransformReader.h +++ b/source/blender/collada/TransformReader.h @@ -37,31 +37,36 @@ //struct Object; -class TransformReader -{ -protected: +class TransformReader { + protected: + UnitConverter *unit_converter; - UnitConverter *unit_converter; + public: + struct Animation { + Object *ob; + COLLADAFW::Node *node; + COLLADAFW::Transformation *tm; // which transform is animated by an AnimationList->id + }; -public: - struct Animation { - Object *ob; - COLLADAFW::Node *node; - COLLADAFW::Transformation *tm; // which transform is animated by an AnimationList->id - }; + TransformReader(UnitConverter *conv); - TransformReader(UnitConverter *conv); + void get_node_mat(float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob); + void get_node_mat(float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob, + float parent_mat[4][4]); - void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob); - void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob, float parent_mat[4][4]); - - void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); - void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); - void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); - void dae_matrix_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); - void dae_translate_to_v3(COLLADAFW::Transformation *tm, float v[3]); - void dae_scale_to_v3(COLLADAFW::Transformation *tm, float v[3]); - void dae_vector3_to_v3(const COLLADABU::Math::Vector3 &v3, float v[3]); + void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); + void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); + void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); + void dae_matrix_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); + void dae_translate_to_v3(COLLADAFW::Transformation *tm, float v[3]); + void dae_scale_to_v3(COLLADAFW::Transformation *tm, float v[3]); + void dae_vector3_to_v3(const COLLADABU::Math::Vector3 &v3, float v[3]); }; #endif diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index 7b5356d2dce..8ebf529cc25 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - #include "BLI_math.h" #include "BLI_sys_types.h" @@ -26,125 +25,126 @@ #include "TransformWriter.h" -void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4], bool limit_precision) +void TransformWriter::add_node_transform(COLLADASW::Node &node, + float mat[4][4], + float parent_mat[4][4], + bool limit_precision) { - float loc[3], rot[3], scale[3]; - float local[4][4]; - - if (parent_mat) { - float invpar[4][4]; - invert_m4_m4(invpar, parent_mat); - mul_m4_m4m4(local, invpar, mat); - } - else { - copy_m4_m4(local, mat); - } - - double dmat[4][4]; - UnitConverter *converter = new UnitConverter(); - converter->mat4_to_dae_double(dmat, local); - delete converter; - - bc_decompose(local, loc, rot, NULL, scale); - - if (node.getType() == COLLADASW::Node::JOINT) { - // XXX Why are joints handled differently ? - node.addMatrix("transform", dmat); - } - else { - add_transform(node, loc, rot, scale); - } + float loc[3], rot[3], scale[3]; + float local[4][4]; + + if (parent_mat) { + float invpar[4][4]; + invert_m4_m4(invpar, parent_mat); + mul_m4_m4m4(local, invpar, mat); + } + else { + copy_m4_m4(local, mat); + } + + double dmat[4][4]; + UnitConverter *converter = new UnitConverter(); + converter->mat4_to_dae_double(dmat, local); + delete converter; + + bc_decompose(local, loc, rot, NULL, scale); + + if (node.getType() == COLLADASW::Node::JOINT) { + // XXX Why are joints handled differently ? + node.addMatrix("transform", dmat); + } + else { + add_transform(node, loc, rot, scale); + } } -void TransformWriter::add_node_transform_ob( - COLLADASW::Node& node, - Object *ob, - BC_export_transformation_type transformation_type, - bool limit_precision) +void TransformWriter::add_node_transform_ob(COLLADASW::Node &node, + Object *ob, + BC_export_transformation_type transformation_type, + bool limit_precision) { #if 0 - float rot[3], loc[3], scale[3]; + float rot[3], loc[3], scale[3]; - if (ob->parent) { - float C[4][4], tmat[4][4], imat[4][4], mat[4][4]; + if (ob->parent) { + float C[4][4], tmat[4][4], imat[4][4], mat[4][4]; - // factor out scale from obmat + // factor out scale from obmat - copy_v3_v3(scale, ob->scale); + copy_v3_v3(scale, ob->scale); - ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f; - BKE_object_to_mat4(ob, C); - copy_v3_v3(ob->scale, scale); + ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f; + BKE_object_to_mat4(ob, C); + copy_v3_v3(ob->scale, scale); - mul_m4_series(tmat, ob->parent->obmat, ob->parentinv, C); + mul_m4_series(tmat, ob->parent->obmat, ob->parentinv, C); - // calculate local mat + // calculate local mat - invert_m4_m4(imat, ob->parent->obmat); - mul_m4_m4m4(mat, imat, tmat); + invert_m4_m4(imat, ob->parent->obmat); + mul_m4_m4m4(mat, imat, tmat); - // done + // done - mat4_to_eul(rot, mat); - copy_v3_v3(loc, mat[3]); - } - else { - copy_v3_v3(loc, ob->loc); - copy_v3_v3(rot, ob->rot); - copy_v3_v3(scale, ob->scale); - } + mat4_to_eul(rot, mat); + copy_v3_v3(loc, mat[3]); + } + else { + copy_v3_v3(loc, ob->loc); + copy_v3_v3(rot, ob->rot); + copy_v3_v3(scale, ob->scale); + } - add_transform(node, loc, rot, scale); + add_transform(node, loc, rot, scale); #endif - /* Export the local Matrix (relative to the object parent, be it an object, bone or vertex(-tices)) */ - float f_obmat[4][4]; - BKE_object_matrix_local_get(ob, f_obmat); - - switch (transformation_type) { - case BC_TRANSFORMATION_TYPE_MATRIX: - { - UnitConverter converter; - double d_obmat[4][4]; - converter.mat4_to_dae_double(d_obmat, f_obmat); - if (limit_precision) - bc_sanitize_mat(d_obmat, LIMITTED_PRECISION); - node.addMatrix("transform",d_obmat); - break; - } - case BC_TRANSFORMATION_TYPE_TRANSROTLOC: - { - float loc[3], rot[3], scale[3]; - bc_decompose(f_obmat, loc, rot, NULL, scale); - if (limit_precision) { - bc_sanitize_v3(loc, LIMITTED_PRECISION); - bc_sanitize_v3(rot, LIMITTED_PRECISION); - bc_sanitize_v3(scale, LIMITTED_PRECISION); - } - add_transform(node, loc, rot, scale); - break; - } - } - + /* Export the local Matrix (relative to the object parent, be it an object, bone or vertex(-tices)) */ + float f_obmat[4][4]; + BKE_object_matrix_local_get(ob, f_obmat); + + switch (transformation_type) { + case BC_TRANSFORMATION_TYPE_MATRIX: { + UnitConverter converter; + double d_obmat[4][4]; + converter.mat4_to_dae_double(d_obmat, f_obmat); + if (limit_precision) + bc_sanitize_mat(d_obmat, LIMITTED_PRECISION); + node.addMatrix("transform", d_obmat); + break; + } + case BC_TRANSFORMATION_TYPE_TRANSROTLOC: { + float loc[3], rot[3], scale[3]; + bc_decompose(f_obmat, loc, rot, NULL, scale); + if (limit_precision) { + bc_sanitize_v3(loc, LIMITTED_PRECISION); + bc_sanitize_v3(rot, LIMITTED_PRECISION); + bc_sanitize_v3(scale, LIMITTED_PRECISION); + } + add_transform(node, loc, rot, scale); + break; + } + } } -void TransformWriter::add_node_transform_identity(COLLADASW::Node& node) +void TransformWriter::add_node_transform_identity(COLLADASW::Node &node) { - float loc[3] = {0.0f, 0.0f, 0.0f}, scale[3] = {1.0f, 1.0f, 1.0f}, rot[3] = {0.0f, 0.0f, 0.0f}; - add_transform(node, loc, rot, scale); + float loc[3] = {0.0f, 0.0f, 0.0f}, scale[3] = {1.0f, 1.0f, 1.0f}, rot[3] = {0.0f, 0.0f, 0.0f}; + add_transform(node, loc, rot, scale); } -void TransformWriter::add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3]) +void TransformWriter::add_transform(COLLADASW::Node &node, + float loc[3], + float rot[3], + float scale[3]) { #if 0 - node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2])); - node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1])); - node.addRotateX("rotationX", COLLADABU::Math::Utils::radToDegF(rot[0])); + node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2])); + node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1])); + node.addRotateX("rotationX", COLLADABU::Math::Utils::radToDegF(rot[0])); #endif - node.addTranslate("location", loc[0], loc[1], loc[2]); - node.addRotateZ("rotationZ", RAD2DEGF(rot[2])); - node.addRotateY("rotationY", RAD2DEGF(rot[1])); - node.addRotateX("rotationX", RAD2DEGF(rot[0])); - node.addScale("scale", scale[0], scale[1], scale[2]); - + node.addTranslate("location", loc[0], loc[1], loc[2]); + node.addRotateZ("rotationZ", RAD2DEGF(rot[2])); + node.addRotateY("rotationY", RAD2DEGF(rot[1])); + node.addRotateX("rotationX", RAD2DEGF(rot[0])); + node.addScale("scale", scale[0], scale[1], scale[2]); } diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h index 3792ce840ee..22ba0716cfe 100644 --- a/source/blender/collada/TransformWriter.h +++ b/source/blender/collada/TransformWriter.h @@ -29,25 +29,22 @@ #include "collada_utils.h" #include "collada.h" -class TransformWriter -{ -protected: - void add_node_transform( - COLLADASW::Node& node, - float mat[4][4], - float parent_mat[4][4], - bool limit_precision=false); - - void add_node_transform_ob( - COLLADASW::Node& node, - Object *ob, - BC_export_transformation_type transformation_type, - bool limit_precision = false); - - void add_node_transform_identity(COLLADASW::Node& node); - -private: - void add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3]); +class TransformWriter { + protected: + void add_node_transform(COLLADASW::Node &node, + float mat[4][4], + float parent_mat[4][4], + bool limit_precision = false); + + void add_node_transform_ob(COLLADASW::Node &node, + Object *ob, + BC_export_transformation_type transformation_type, + bool limit_precision = false); + + void add_node_transform_identity(COLLADASW::Node &node); + + private: + void add_transform(COLLADASW::Node &node, float loc[3], float rot[3], float scale[3]); }; #endif diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 69030bd2f47..294d105befd 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - /* COLLADABU_ASSERT, may be able to remove later */ #include "COLLADABUPlatform.h" @@ -28,8 +27,7 @@ #include "ImportSettings.h" #include "collada.h" -extern "C" -{ +extern "C" { #include "BKE_scene.h" #include "BKE_context.h" #include "DEG_depsgraph.h" @@ -39,75 +37,77 @@ extern "C" #include "BLI_fileops.h" #include "BLI_linklist.h" - static void print_import_header(ImportSettings &import_settings) { - fprintf(stderr, "+-- Collada Import parameters------\n"); - fprintf(stderr, "| input file : %s\n", import_settings.filepath); - fprintf(stderr, "| use units : %s\n", (import_settings.import_units)?"yes":"no"); - fprintf(stderr, "| autoconnect : %s\n", (import_settings.auto_connect) ? "yes" : "no"); - fprintf(stderr, "+-- Armature Import parameters ----\n"); - fprintf(stderr, "| find bone chains: %s\n", (import_settings.find_chains) ? "yes" : "no"); - fprintf(stderr, "| min chain len : %d\n", import_settings.min_chain_length); - fprintf(stderr, "| fix orientation : %s\n", (import_settings.fix_orientation) ? "yes" : "no"); - fprintf(stderr, "| keep bind info : %s\n", (import_settings.keep_bind_info) ? "yes" : "no"); - + fprintf(stderr, "+-- Collada Import parameters------\n"); + fprintf(stderr, "| input file : %s\n", import_settings.filepath); + fprintf(stderr, "| use units : %s\n", (import_settings.import_units) ? "yes" : "no"); + fprintf(stderr, "| autoconnect : %s\n", (import_settings.auto_connect) ? "yes" : "no"); + fprintf(stderr, "+-- Armature Import parameters ----\n"); + fprintf(stderr, "| find bone chains: %s\n", (import_settings.find_chains) ? "yes" : "no"); + fprintf(stderr, "| min chain len : %d\n", import_settings.min_chain_length); + fprintf(stderr, "| fix orientation : %s\n", (import_settings.fix_orientation) ? "yes" : "no"); + fprintf(stderr, "| keep bind info : %s\n", (import_settings.keep_bind_info) ? "yes" : "no"); } static void print_import_footer(int status) { - fprintf(stderr, "+----------------------------------\n"); - fprintf(stderr, "| Collada Import : %s\n", (status)? "OK":"FAIL"); - fprintf(stderr, "+----------------------------------\n"); + fprintf(stderr, "+----------------------------------\n"); + fprintf(stderr, "| Collada Import : %s\n", (status) ? "OK" : "FAIL"); + fprintf(stderr, "+----------------------------------\n"); } int collada_import(bContext *C, ImportSettings *import_settings) { - print_import_header(*import_settings); - DocumentImporter imp(C, import_settings); - int status = imp.import()? 1:0; - print_import_footer(status); + print_import_header(*import_settings); + DocumentImporter imp(C, import_settings); + int status = imp.import() ? 1 : 0; + print_import_footer(status); - return status; + return status; } -int collada_export(bContext *C, - ExportSettings *export_settings) +int collada_export(bContext *C, ExportSettings *export_settings) { - BlenderContext blender_context(C); - ViewLayer *view_layer = blender_context.get_view_layer(); - - int includeFilter = OB_REL_NONE; - if (export_settings->include_armatures) includeFilter |= OB_REL_MOD_ARMATURE; - if (export_settings->include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE; - - /* Fetch the complete set of exported objects - * ATTENTION: Invisible objects will not be exported - */ - eObjectSet objectSet = (export_settings->selected) ? OB_SET_SELECTED : OB_SET_ALL; - export_settings->export_set = BKE_object_relational_superset(view_layer, objectSet, (eObRelationTypes)includeFilter); - - int export_count = BLI_linklist_count(export_settings->export_set); - - if (export_count == 0) { - if (export_settings->selected) { - fprintf(stderr, "Collada: Found no objects to export.\nPlease ensure that all objects which shall be exported are also visible in the 3D Viewport.\n"); - } - else { - fprintf(stderr, "Collada: Your scene seems to be empty. No Objects will be exported.\n"); - } - } - else { - if (export_settings->sort_by_name) - bc_bubble_sort_by_Object_name(export_settings->export_set); - } - - DocumentExporter exporter(blender_context, export_settings); - int status = exporter.exportCurrentScene(); - - BLI_linklist_free(export_settings->export_set, NULL); - - return (status) ? -1:export_count; + BlenderContext blender_context(C); + ViewLayer *view_layer = blender_context.get_view_layer(); + + int includeFilter = OB_REL_NONE; + if (export_settings->include_armatures) + includeFilter |= OB_REL_MOD_ARMATURE; + if (export_settings->include_children) + includeFilter |= OB_REL_CHILDREN_RECURSIVE; + + /* Fetch the complete set of exported objects + * ATTENTION: Invisible objects will not be exported + */ + eObjectSet objectSet = (export_settings->selected) ? OB_SET_SELECTED : OB_SET_ALL; + export_settings->export_set = BKE_object_relational_superset( + view_layer, objectSet, (eObRelationTypes)includeFilter); + + int export_count = BLI_linklist_count(export_settings->export_set); + + if (export_count == 0) { + if (export_settings->selected) { + fprintf(stderr, + "Collada: Found no objects to export.\nPlease ensure that all objects which shall " + "be exported are also visible in the 3D Viewport.\n"); + } + else { + fprintf(stderr, "Collada: Your scene seems to be empty. No Objects will be exported.\n"); + } + } + else { + if (export_settings->sort_by_name) + bc_bubble_sort_by_Object_name(export_settings->export_set); + } + + DocumentExporter exporter(blender_context, export_settings); + int status = exporter.exportCurrentScene(); + + BLI_linklist_free(export_settings->export_set, NULL); + + return (status) ? -1 : export_count; } /* end extern C */ diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index 2e407c30700..df6e72cbf3a 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -42,11 +42,9 @@ struct bContext; /* * both return 1 on success, 0 on error */ -int collada_import(struct bContext *C, - ImportSettings *import_settings); +int collada_import(struct bContext *C, ImportSettings *import_settings); -int collada_export(struct bContext *C, - ExportSettings *export_settings); +int collada_export(struct bContext *C, ExportSettings *export_settings); #ifdef __cplusplus } diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 637a5dde3ea..b95a51e5273 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - /* COLLADABU_ASSERT, may be able to remove later */ #include "COLLADABUPlatform.h" #include "collada_utils.h" @@ -28,133 +27,132 @@ UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP) { - axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI); - axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI); + axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI); + axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI); - unit_m4(z_up_mat4); - unit_m4(scale_mat4); + unit_m4(z_up_mat4); + unit_m4(scale_mat4); } void UnitConverter::read_asset(const COLLADAFW::FileInfo *asset) { - unit = asset->getUnit(); - up_axis = asset->getUpAxisType(); + unit = asset->getUnit(); + up_axis = asset->getUpAxisType(); } UnitConverter::UnitSystem UnitConverter::isMetricSystem() { - switch (unit.getLinearUnitUnit()) { - case COLLADAFW::FileInfo::Unit::MILLIMETER: - case COLLADAFW::FileInfo::Unit::CENTIMETER: - case COLLADAFW::FileInfo::Unit::DECIMETER: - case COLLADAFW::FileInfo::Unit::METER: - case COLLADAFW::FileInfo::Unit::KILOMETER: - return UnitConverter::Metric; - case COLLADAFW::FileInfo::Unit::INCH: - case COLLADAFW::FileInfo::Unit::FOOT: - case COLLADAFW::FileInfo::Unit::YARD: - return UnitConverter::Imperial; - default: - return UnitConverter::None; - } + switch (unit.getLinearUnitUnit()) { + case COLLADAFW::FileInfo::Unit::MILLIMETER: + case COLLADAFW::FileInfo::Unit::CENTIMETER: + case COLLADAFW::FileInfo::Unit::DECIMETER: + case COLLADAFW::FileInfo::Unit::METER: + case COLLADAFW::FileInfo::Unit::KILOMETER: + return UnitConverter::Metric; + case COLLADAFW::FileInfo::Unit::INCH: + case COLLADAFW::FileInfo::Unit::FOOT: + case COLLADAFW::FileInfo::Unit::YARD: + return UnitConverter::Imperial; + default: + return UnitConverter::None; + } } float UnitConverter::getLinearMeter() { - return (float)unit.getLinearUnitMeter(); + return (float)unit.getLinearUnitMeter(); } void UnitConverter::convertVector3(COLLADABU::Math::Vector3 &vec, float *v) { - v[0] = vec.x; - v[1] = vec.y; - v[2] = vec.z; + v[0] = vec.x; + v[1] = vec.y; + v[2] = vec.z; } // TODO need also for angle conversion, time conversion... -void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4& in) +void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in) { - // in DAE, matrices use columns vectors, (see comments in COLLADABUMathMatrix4.h) - // so here, to make a blender matrix, we swap columns and rows - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - out[i][j] = in[j][i]; - } - } + // in DAE, matrices use columns vectors, (see comments in COLLADABUMathMatrix4.h) + // so here, to make a blender matrix, we swap columns and rows + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + out[i][j] = in[j][i]; + } + } } void UnitConverter::mat4_to_dae(float out[4][4], float in[4][4]) { - transpose_m4_m4(out, in); + transpose_m4_m4(out, in); } void UnitConverter::mat4_to_dae_double(double out[4][4], float in[4][4]) { - float mat[4][4]; + float mat[4][4]; - mat4_to_dae(mat, in); + mat4_to_dae(mat, in); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - out[i][j] = mat[i][j]; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + out[i][j] = mat[i][j]; } -float(&UnitConverter::get_rotation())[4][4] +float (&UnitConverter::get_rotation())[4][4] { - switch (up_axis) { - case COLLADAFW::FileInfo::X_UP: - return x_up_mat4; - break; - case COLLADAFW::FileInfo::Y_UP: - return y_up_mat4; - break; - default: - return z_up_mat4; - break; - } + switch (up_axis) { + case COLLADAFW::FileInfo::X_UP: + return x_up_mat4; + break; + case COLLADAFW::FileInfo::Y_UP: + return y_up_mat4; + break; + default: + return z_up_mat4; + break; + } } - -float(&UnitConverter::get_scale())[4][4] +float (&UnitConverter::get_scale())[4][4] { - return scale_mat4; + return scale_mat4; } void UnitConverter::calculate_scale(Scene &sce) { - PointerRNA scene_ptr, unit_settings; - PropertyRNA *system_ptr, *scale_ptr; - RNA_id_pointer_create(&sce.id, &scene_ptr); + PointerRNA scene_ptr, unit_settings; + PropertyRNA *system_ptr, *scale_ptr; + RNA_id_pointer_create(&sce.id, &scene_ptr); - unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings"); - system_ptr = RNA_struct_find_property(&unit_settings, "system"); - scale_ptr = RNA_struct_find_property(&unit_settings, "scale_length"); + unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings"); + system_ptr = RNA_struct_find_property(&unit_settings, "system"); + scale_ptr = RNA_struct_find_property(&unit_settings, "scale_length"); - int type = RNA_property_enum_get(&unit_settings, system_ptr); + int type = RNA_property_enum_get(&unit_settings, system_ptr); - float bl_scale; + float bl_scale; - switch (type) { - case USER_UNIT_NONE: - bl_scale = 1.0; // map 1 Blender unit to 1 Meter - break; + switch (type) { + case USER_UNIT_NONE: + bl_scale = 1.0; // map 1 Blender unit to 1 Meter + break; - case USER_UNIT_METRIC: - bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); - break; + case USER_UNIT_METRIC: + bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); + break; - default : - bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); - // it looks like the conversion to Imperial is done implicitly. - // So nothing to do here. - break; - } + default: + bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); + // it looks like the conversion to Imperial is done implicitly. + // So nothing to do here. + break; + } - float rescale[3]; - rescale[0] = rescale[1] = rescale[2] = getLinearMeter() / bl_scale; + float rescale[3]; + rescale[0] = rescale[1] = rescale[2] = getLinearMeter() / bl_scale; - size_to_mat4(scale_mat4, rescale); + size_to_mat4(scale_mat4, rescale); } /** @@ -168,212 +166,173 @@ void UnitConverter::calculate_scale(Scene &sce) */ const unsigned char translate_start_name_map[256] = { - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 95, 95, 95, 95, 95, - 95, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 95, 95, 95, 95, 95, - - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 95, 95, 95, 95, + 95, 95, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 95, 95, 95, 95, 95, + + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, }; const unsigned char translate_name_map[256] = { - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 45, 95, 95, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 95, 95, 95, 95, 95, 95, - 95, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 95, 95, 95, 95, 95, - 95, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 95, 95, 95, 95, 95, - - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 45, 95, 95, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 95, 95, 95, 95, 95, 95, 95, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 95, 95, 95, 95, + 95, 95, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 95, 95, 95, 95, 95, + + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, }; -typedef std::map< std::string, std::vector<std::string> > map_string_list; +typedef std::map<std::string, std::vector<std::string>> map_string_list; map_string_list global_id_map; void clear_global_id_map() { - global_id_map.clear(); + global_id_map.clear(); } /** Look at documentation of translate_map */ std::string translate_id(const char *idString) { - std::string id = std::string(idString); - return translate_id(id); + std::string id = std::string(idString); + return translate_id(id); } std::string translate_id(const std::string &id) { - if (id.size() == 0) { - return id; - } - - std::string id_translated = id; - id_translated[0] = translate_start_name_map[(unsigned int)id_translated[0]]; - for (unsigned int i = 1; i < id_translated.size(); i++) { - id_translated[i] = translate_name_map[(unsigned int)id_translated[i]]; - } - // It's so much workload now, the if () should speed up things. - if (id_translated != id) { - // Search duplicates - map_string_list::iterator iter = global_id_map.find(id_translated); - if (iter != global_id_map.end()) { - unsigned int i = 0; - bool found = false; - for (i = 0; i < iter->second.size(); i++) { - if (id == iter->second[i]) { - found = true; - break; - } - } - bool convert = false; - if (found) { - if (i > 0) { - convert = true; - } - } - else { - convert = true; - global_id_map[id_translated].push_back(id); - } - if (convert) { - std::stringstream out; - out << ++i; - id_translated += out.str(); - } - } - else { global_id_map[id_translated].push_back(id); } - } - return id_translated; + if (id.size() == 0) { + return id; + } + + std::string id_translated = id; + id_translated[0] = translate_start_name_map[(unsigned int)id_translated[0]]; + for (unsigned int i = 1; i < id_translated.size(); i++) { + id_translated[i] = translate_name_map[(unsigned int)id_translated[i]]; + } + // It's so much workload now, the if () should speed up things. + if (id_translated != id) { + // Search duplicates + map_string_list::iterator iter = global_id_map.find(id_translated); + if (iter != global_id_map.end()) { + unsigned int i = 0; + bool found = false; + for (i = 0; i < iter->second.size(); i++) { + if (id == iter->second[i]) { + found = true; + break; + } + } + bool convert = false; + if (found) { + if (i > 0) { + convert = true; + } + } + else { + convert = true; + global_id_map[id_translated].push_back(id); + } + if (convert) { + std::stringstream out; + out << ++i; + id_translated += out.str(); + } + } + else { + global_id_map[id_translated].push_back(id); + } + } + return id_translated; } std::string id_name(void *id) { - return ((ID *)id)->name + 2; + return ((ID *)id)->name + 2; } std::string encode_xml(std::string xml) { - const std::map<char, std::string> escape { - {'<' , "<" }, - {'>' , ">" }, - {'"' , """}, - {'\'', "'"}, - {'&' , "&" } - }; - - std::map<char, std::string>::const_iterator it; - std::string encoded_xml = ""; - - for (unsigned int i = 0; i < xml.size(); i++) { - char c = xml.at(i); - it = escape.find(c); - - if (it == escape.end()) { - encoded_xml += c; - } - else { - encoded_xml += it->second; - } - } - return encoded_xml; + const std::map<char, std::string> escape{ + {'<', "<"}, {'>', ">"}, {'"', """}, {'\'', "'"}, {'&', "&"}}; + + std::map<char, std::string>::const_iterator it; + std::string encoded_xml = ""; + + for (unsigned int i = 0; i < xml.size(); i++) { + char c = xml.at(i); + it = escape.find(c); + + if (it == escape.end()) { + encoded_xml += c; + } + else { + encoded_xml += it->second; + } + } + return encoded_xml; } std::string get_geometry_id(Object *ob) { - return translate_id(id_name(ob->data)) + "-mesh"; + return translate_id(id_name(ob->data)) + "-mesh"; } std::string get_geometry_id(Object *ob, bool use_instantiation) { - std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob); + std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob); - return translate_id(geom_name) + "-mesh"; + return translate_id(geom_name) + "-mesh"; } std::string get_light_id(Object *ob) { - return translate_id(id_name(ob)) + "-light"; + return translate_id(id_name(ob)) + "-light"; } std::string get_joint_sid(Bone *bone) { - return translate_id(bone->name); + return translate_id(bone->name); } std::string get_joint_sid(EditBone *bone) { - return translate_id(bone->name); + return translate_id(bone->name); } std::string get_camera_id(Object *ob) { - return translate_id(id_name(ob)) + "-camera"; + return translate_id(id_name(ob)) + "-camera"; } std::string get_effect_id(Material *mat) { - return translate_id(id_name(mat)) + "-effect"; + return translate_id(id_name(mat)) + "-effect"; } std::string get_material_id(Material *mat) { - return translate_id(id_name(mat)) + "-material"; + return translate_id(id_name(mat)) + "-material"; } std::string get_morph_id(Object *ob) { - return translate_id(id_name(ob)) + "-morph"; + return translate_id(id_name(ob)) + "-morph"; } diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index 23478ae54d6..297ea9c0bbb 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -35,46 +35,43 @@ #include "BLI_math.h" #include "BLI_linklist.h" -class UnitConverter -{ -private: - COLLADAFW::FileInfo::Unit unit; - COLLADAFW::FileInfo::UpAxisType up_axis; +class UnitConverter { + private: + COLLADAFW::FileInfo::Unit unit; + COLLADAFW::FileInfo::UpAxisType up_axis; - float x_up_mat4[4][4]; - float y_up_mat4[4][4]; - float z_up_mat4[4][4]; - float scale_mat4[4][4]; + float x_up_mat4[4][4]; + float y_up_mat4[4][4]; + float z_up_mat4[4][4]; + float scale_mat4[4][4]; -public: + public: + enum UnitSystem { + None, + Metric, + Imperial, + }; - enum UnitSystem { - None, - Metric, - Imperial, - }; + // Initialize with Z_UP, since Blender uses right-handed, z-up + UnitConverter(); - // Initialize with Z_UP, since Blender uses right-handed, z-up - UnitConverter(); + void read_asset(const COLLADAFW::FileInfo *asset); - void read_asset(const COLLADAFW::FileInfo *asset); + void convertVector3(COLLADABU::Math::Vector3 &vec, float *v); - void convertVector3(COLLADABU::Math::Vector3 &vec, float *v); + UnitConverter::UnitSystem isMetricSystem(void); - UnitConverter::UnitSystem isMetricSystem(void); + float getLinearMeter(void); - float getLinearMeter(void); + // TODO need also for angle conversion, time conversion... - // TODO need also for angle conversion, time conversion... - - static void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4& in); - static void mat4_to_dae(float out[4][4], float in[4][4]); - static void mat4_to_dae_double(double out[4][4], float in[4][4]); - - float(&get_rotation())[4][4]; - float(&get_scale())[4][4]; - void calculate_scale(Scene &sce); + static void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in); + static void mat4_to_dae(float out[4][4], float in[4][4]); + static void mat4_to_dae_double(double out[4][4], float in[4][4]); + float (&get_rotation())[4][4]; + float (&get_scale())[4][4]; + void calculate_scale(Scene &sce); }; extern void clear_global_id_map(); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 0084ff84e4d..2e964bbf108 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -18,7 +18,6 @@ * \ingroup collada */ - /* COLLADABU_ASSERT, may be able to remove later */ #include "COLLADABUPlatform.h" @@ -64,7 +63,7 @@ extern "C" { #include "MEM_guardedalloc.h" -#include "WM_api.h" // XXX hrm, see if we can do without this +#include "WM_api.h" // XXX hrm, see if we can do without this #include "WM_types.h" #include "bmesh.h" @@ -73,7 +72,7 @@ extern "C" { #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" #if 0 -#include "NOD_common.h" +# include "NOD_common.h" #endif } @@ -81,233 +80,238 @@ extern "C" { #include "ExportSettings.h" #include "BlenderContext.h" -float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index) +float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index) { - if (index >= array.getValuesCount()) - return 0.0f; + if (index >= array.getValuesCount()) + return 0.0f; - if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT) - return array.getFloatValues()->getData()[index]; - else - return array.getDoubleValues()->getData()[index]; + if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT) + return array.getFloatValues()->getData()[index]; + else + return array.getDoubleValues()->getData()[index]; } // copied from /editors/object/object_relations.c int bc_test_parent_loop(Object *par, Object *ob) { - /* test if 'ob' is a parent somewhere in par's parents */ + /* test if 'ob' is a parent somewhere in par's parents */ - if (par == NULL) return 0; - if (ob == par) return 1; + if (par == NULL) + return 0; + if (ob == par) + return 1; - return bc_test_parent_loop(par->parent, ob); + return bc_test_parent_loop(par->parent, ob); } void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer) { - Base *base; - for (base = (Base *)view_layer->object_bases.first; base; base = base->next) { - Object *cob = base->object; - if (cob->parent == ob) { - switch (ob->type) { - case OB_MESH: - case OB_CAMERA: - case OB_LAMP: - case OB_EMPTY: - case OB_ARMATURE: - child_set.push_back(cob); - default: break; - } - } - } + Base *base; + for (base = (Base *)view_layer->object_bases.first; base; base = base->next) { + Object *cob = base->object; + if (cob->parent == ob) { + switch (ob->type) { + case OB_MESH: + case OB_CAMERA: + case OB_LAMP: + case OB_EMPTY: + case OB_ARMATURE: + child_set.push_back(cob); + default: + break; + } + } + } } bool bc_validateConstraints(bConstraint *con) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - /* these we can skip completely (invalid constraints...) */ - if (cti == NULL) - return false; - if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) - return false; + /* these we can skip completely (invalid constraints...) */ + if (cti == NULL) + return false; + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) + return false; - /* these constraints can't be evaluated anyway */ - if (cti->evaluate_constraint == NULL) - return false; + /* these constraints can't be evaluated anyway */ + if (cti->evaluate_constraint == NULL) + return false; - /* influence == 0 should be ignored */ - if (con->enforce == 0.0f) - return false; + /* influence == 0 should be ignored */ + if (con->enforce == 0.0f) + return false; - /* validation passed */ - return true; + /* validation passed */ + return true; } // a shortened version of parent_set_exec() // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) { - Object workob; - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *sce = CTX_data_scene(C); + Object workob; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *sce = CTX_data_scene(C); - if (!par || bc_test_parent_loop(par, ob)) - return false; + if (!par || bc_test_parent_loop(par, ob)) + return false; - ob->parent = par; - ob->partype = PAROBJECT; + ob->parent = par; + ob->partype = PAROBJECT; - ob->parsubstr[0] = 0; + ob->parsubstr[0] = 0; - if (is_parent_space) { - float mat[4][4]; - // calc par->obmat - BKE_object_where_is_calc(depsgraph, sce, par); + if (is_parent_space) { + float mat[4][4]; + // calc par->obmat + BKE_object_where_is_calc(depsgraph, sce, par); - // move child obmat into world space - mul_m4_m4m4(mat, par->obmat, ob->obmat); - copy_m4_m4(ob->obmat, mat); - } + // move child obmat into world space + mul_m4_m4m4(mat, par->obmat, ob->obmat); + copy_m4_m4(ob->obmat, mat); + } - // apply child obmat (i.e. decompose it into rot/loc/size) - BKE_object_apply_mat4(ob, ob->obmat, 0, 0); + // apply child obmat (i.e. decompose it into rot/loc/size) + BKE_object_apply_mat4(ob, ob->obmat, 0, 0); - // compute parentinv - BKE_object_workob_calc_parent(depsgraph, sce, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); + // compute parentinv + BKE_object_workob_calc_parent(depsgraph, sce, ob, &workob); + invert_m4_m4(ob->parentinv, workob.obmat); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM); + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM); - return true; + return true; } std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions) { - std::vector<bAction *> actions; - if (all_actions) { - Main *bmain = CTX_data_main(C); - ID *id; - - for (id = (ID *)bmain->actions.first; id; id = (ID *)(id->next)) { - bAction *act = (bAction *)id; - /* XXX This currently creates too many actions. - TODO Need to check if the action is compatible to the given object - */ - actions.push_back(act); - } - } - else - { - bAction *action = bc_getSceneObjectAction(ob); - actions.push_back(action); - } - - return actions; -} - -std::string bc_get_action_id(std::string action_name, std::string ob_name, std::string channel_type, std::string axis_name, std::string axis_separator) -{ - std::string result = action_name + "_" + channel_type; - if (ob_name.length() > 0) - result = ob_name + "_" + result; - if (axis_name.length() > 0) - result += axis_separator + axis_name; - return translate_id(result); + std::vector<bAction *> actions; + if (all_actions) { + Main *bmain = CTX_data_main(C); + ID *id; + + for (id = (ID *)bmain->actions.first; id; id = (ID *)(id->next)) { + bAction *act = (bAction *)id; + /* XXX This currently creates too many actions. + TODO Need to check if the action is compatible to the given object + */ + actions.push_back(act); + } + } + else { + bAction *action = bc_getSceneObjectAction(ob); + actions.push_back(action); + } + + return actions; +} + +std::string bc_get_action_id(std::string action_name, + std::string ob_name, + std::string channel_type, + std::string axis_name, + std::string axis_separator) +{ + std::string result = action_name + "_" + channel_type; + if (ob_name.length() > 0) + result = ob_name + "_" + result; + if (axis_name.length() > 0) + result += axis_separator + axis_name; + return translate_id(result); } void bc_update_scene(BlenderContext &blender_context, float ctime) { - Main *bmain = blender_context.get_main(); - Scene *scene = blender_context.get_scene(); - Depsgraph *depsgraph = blender_context.get_depsgraph(); + Main *bmain = blender_context.get_main(); + Scene *scene = blender_context.get_scene(); + Depsgraph *depsgraph = blender_context.get_depsgraph(); - /* - * See remark in physics_fluid.c lines 395...) - * BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay); - */ - BKE_scene_frame_set(scene, ctime); - ED_update_for_newframe(bmain, depsgraph); + /* + * See remark in physics_fluid.c lines 395...) + * BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay); + */ + BKE_scene_frame_set(scene, ctime); + ED_update_for_newframe(bmain, depsgraph); } Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) { - Object *ob = BKE_object_add_only_object(bmain, type, name); - - ob->data = BKE_object_obdata_add_from_type(bmain, type, name); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); - - LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); - BKE_collection_object_add(bmain, layer_collection->collection, ob); - - Base *base = BKE_view_layer_base_find(view_layer, ob); - /* TODO: is setting active needed? */ - BKE_view_layer_base_select_and_set_active(view_layer, base); - - return ob; -} - -Mesh *bc_get_mesh_copy( - BlenderContext &blender_context, - Object *ob, - BC_export_mesh_type export_mesh_type, - bool apply_modifiers, - bool triangulate) -{ - CustomData_MeshMasks mask = CD_MASK_MESH; - Mesh *tmpmesh = NULL; - if (apply_modifiers) { -#if 0 /* Not supported by new system currently... */ - switch (export_mesh_type) { - case BC_MESH_TYPE_VIEW: - { - dm = mesh_create_derived_view(depsgraph, scene, ob, &mask); - break; - } - case BC_MESH_TYPE_RENDER: - { - dm = mesh_create_derived_render(depsgraph, scene, ob, &mask); - break; - } - } + Object *ob = BKE_object_add_only_object(bmain, type, name); + + ob->data = BKE_object_obdata_add_from_type(bmain, type, name); + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + + LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); + BKE_collection_object_add(bmain, layer_collection->collection, ob); + + Base *base = BKE_view_layer_base_find(view_layer, ob); + /* TODO: is setting active needed? */ + BKE_view_layer_base_select_and_set_active(view_layer, base); + + return ob; +} + +Mesh *bc_get_mesh_copy(BlenderContext &blender_context, + Object *ob, + BC_export_mesh_type export_mesh_type, + bool apply_modifiers, + bool triangulate) +{ + CustomData_MeshMasks mask = CD_MASK_MESH; + Mesh *tmpmesh = NULL; + if (apply_modifiers) { +#if 0 /* Not supported by new system currently... */ + switch (export_mesh_type) { + case BC_MESH_TYPE_VIEW: + { + dm = mesh_create_derived_view(depsgraph, scene, ob, &mask); + break; + } + case BC_MESH_TYPE_RENDER: + { + dm = mesh_create_derived_render(depsgraph, scene, ob, &mask); + break; + } + } #else - Depsgraph *depsgraph = blender_context.get_depsgraph(); - Scene *scene_eval = blender_context.get_evaluated_scene(); - Object *ob_eval = blender_context.get_evaluated_object(ob); - tmpmesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &mask); + Depsgraph *depsgraph = blender_context.get_depsgraph(); + Scene *scene_eval = blender_context.get_evaluated_scene(); + Object *ob_eval = blender_context.get_evaluated_object(ob); + tmpmesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &mask); #endif - } - else { - tmpmesh = (Mesh *)ob->data; - } + } + else { + tmpmesh = (Mesh *)ob->data; + } - BKE_id_copy_ex(NULL, &tmpmesh->id, (ID **)&tmpmesh, LIB_ID_COPY_LOCALIZE); + BKE_id_copy_ex(NULL, &tmpmesh->id, (ID **)&tmpmesh, LIB_ID_COPY_LOCALIZE); - if (triangulate) { - bc_triangulate_mesh(tmpmesh); - } - BKE_mesh_tessface_ensure(tmpmesh); - return tmpmesh; + if (triangulate) { + bc_triangulate_mesh(tmpmesh); + } + BKE_mesh_tessface_ensure(tmpmesh); + return tmpmesh; } Object *bc_get_assigned_armature(Object *ob) { - Object *ob_arm = NULL; + Object *ob_arm = NULL; - if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { - ob_arm = ob->parent; - } - else { - ModifierData *mod; - for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) { - if (mod->type == eModifierType_Armature) { - ob_arm = ((ArmatureModifierData *)mod)->object; - } - } - } + if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { + ob_arm = ob->parent; + } + else { + ModifierData *mod; + for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) { + if (mod->type == eModifierType_Armature) { + ob_arm = ((ArmatureModifierData *)mod)->object; + } + } + } - return ob_arm; + return ob_arm; } /** @@ -319,92 +323,90 @@ Object *bc_get_assigned_armature(Object *ob) Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob) { - Object *ancestor = ob; - while (ob->parent && bc_is_marked(ob->parent)) { - ob = ob->parent; - ancestor = ob; - } - return ancestor; + Object *ancestor = ob; + while (ob->parent && bc_is_marked(ob->parent)) { + ob = ob->parent; + ancestor = ob; + } + return ancestor; } bool bc_is_base_node(LinkNode *export_set, Object *ob) { - Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob); - return (root == ob); + Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob); + return (root == ob); } bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer) { - bool to_export = (BLI_linklist_index(export_set, ob) != -1); + bool to_export = (BLI_linklist_index(export_set, ob) != -1); - if (!to_export) - { - /* Mark this object as to_export even if it is not in the - export list, but it contains children to export */ + if (!to_export) { + /* Mark this object as to_export even if it is not in the + export list, but it contains children to export */ - std::vector<Object *> children; - bc_get_children(children, ob, view_layer); - for (int i = 0; i < children.size(); i++) { - if (bc_is_in_Export_set(export_set, children[i], view_layer)) { - to_export = true; - break; - } - } - } - return to_export; + std::vector<Object *> children; + bc_get_children(children, ob, view_layer); + for (int i = 0; i < children.size(); i++) { + if (bc_is_in_Export_set(export_set, children[i], view_layer)) { + to_export = true; + break; + } + } + } + return to_export; } bool bc_has_object_type(LinkNode *export_set, short obtype) { - LinkNode *node; + LinkNode *node; - for (node = export_set; node; node = node->next) { - Object *ob = (Object *)node->link; - /* XXX - why is this checking for ob->data? - we could be looking for empties */ - if (ob->type == obtype && ob->data) { - return true; - } - } - return false; + for (node = export_set; node; node = node->next) { + Object *ob = (Object *)node->link; + /* XXX - why is this checking for ob->data? - we could be looking for empties */ + if (ob->type == obtype && ob->data) { + return true; + } + } + return false; } int bc_is_marked(Object *ob) { - return ob && (ob->id.tag & LIB_TAG_DOIT); + return ob && (ob->id.tag & LIB_TAG_DOIT); } void bc_remove_mark(Object *ob) { - ob->id.tag &= ~LIB_TAG_DOIT; + ob->id.tag &= ~LIB_TAG_DOIT; } void bc_set_mark(Object *ob) { - ob->id.tag |= LIB_TAG_DOIT; + ob->id.tag |= LIB_TAG_DOIT; } // Use bubble sort algorithm for sorting the export set void bc_bubble_sort_by_Object_name(LinkNode *export_set) { - bool sorted = false; - LinkNode *node; - for (node = export_set; node->next && !sorted; node = node->next) { - - sorted = true; + bool sorted = false; + LinkNode *node; + for (node = export_set; node->next && !sorted; node = node->next) { - LinkNode *current; - for (current = export_set; current->next; current = current->next) { - Object *a = (Object *)current->link; - Object *b = (Object *)current->next->link; + sorted = true; - if (strcmp(a->id.name, b->id.name) > 0) { - current->link = b; - current->next->link = a; - sorted = false; - } + LinkNode *current; + for (current = export_set; current->next; current = current->next) { + Object *a = (Object *)current->link; + Object *b = (Object *)current->next->link; - } - } + if (strcmp(a->id.name, b->id.name) > 0) { + current->link = b; + current->next->link = a; + sorted = false; + } + } + } } /* Check if a bone is the top most exportable bone in the bone hierarchy. @@ -414,43 +416,44 @@ void bc_bubble_sort_by_Object_name(LinkNode *export_set) */ bool bc_is_root_bone(Bone *aBone, bool deform_bones_only) { - if (deform_bones_only) { - Bone *root = NULL; - Bone *bone = aBone; - while (bone) { - if (!(bone->flag & BONE_NO_DEFORM)) - root = bone; - bone = bone->parent; - } - return (aBone == root); - } - else - return !(aBone->parent); + if (deform_bones_only) { + Bone *root = NULL; + Bone *bone = aBone; + while (bone) { + if (!(bone->flag & BONE_NO_DEFORM)) + root = bone; + bone = bone->parent; + } + return (aBone == root); + } + else + return !(aBone->parent); } int bc_get_active_UVLayer(Object *ob) { - Mesh *me = (Mesh *)ob->data; - return CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); + Mesh *me = (Mesh *)ob->data; + return CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); } std::string bc_url_encode(std::string data) { - /* XXX We probably do not need to do a full encoding. - * But in case that is necessary,then it can be added here. - */ - return bc_replace_string(data,"#", "%23"); + /* XXX We probably do not need to do a full encoding. + * But in case that is necessary,then it can be added here. + */ + return bc_replace_string(data, "#", "%23"); } -std::string bc_replace_string(std::string data, const std::string& pattern, - const std::string& replacement) +std::string bc_replace_string(std::string data, + const std::string &pattern, + const std::string &replacement) { - size_t pos = 0; - while ((pos = data.find(pattern, pos)) != std::string::npos) { - data.replace(pos, pattern.length(), replacement); - pos += replacement.length(); - } - return data; + size_t pos = 0; + while ((pos = data.find(pattern, pos)) != std::string::npos) { + data.replace(pos, pattern.length(), replacement); + pos += replacement.length(); + } + return data; } /** @@ -461,26 +464,24 @@ std::string bc_replace_string(std::string data, const std::string& pattern, void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene) { - if (scale_to_scene) { - mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat); - } - mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat); - BKE_object_apply_mat4(ob, ob->obmat, 0, 0); + if (scale_to_scene) { + mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat); + } + mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat); + BKE_object_apply_mat4(ob, ob->obmat, 0, 0); } void bc_match_scale(std::vector<Object *> *objects_done, - UnitConverter &bc_unit, - bool scale_to_scene) + UnitConverter &bc_unit, + bool scale_to_scene) { - for (std::vector<Object *>::iterator it = objects_done->begin(); - it != objects_done->end(); - ++it) - { - Object *ob = *it; - if (ob -> parent == NULL) { - bc_match_scale(*it, bc_unit, scale_to_scene); - } - } + for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); + ++it) { + Object *ob = *it; + if (ob->parent == NULL) { + bc_match_scale(*it, bc_unit, scale_to_scene); + } + } } /* @@ -488,21 +489,21 @@ void bc_match_scale(std::vector<Object *> *objects_done, */ void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size) { - if (size) { - mat4_to_size(size, mat); - } + if (size) { + mat4_to_size(size, mat); + } - if (eul) { - mat4_to_eul(eul, mat); - } + if (eul) { + mat4_to_eul(eul, mat); + } - if (quat) { - mat4_to_quat(quat, mat); - } + if (quat) { + mat4_to_quat(quat, mat); + } - if (loc) { - copy_v3_v3(loc, mat[3]); - } + if (loc) { + copy_v3_v3(loc, mat[3]); + } } /* @@ -518,40 +519,39 @@ void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], floa */ void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4]) { - float qd[4]; - float matd[4][4]; - float mati[4][4]; - float mat_from[4][4]; - quat_to_mat4(mat_from, quat_from); + float qd[4]; + float matd[4][4]; + float mati[4][4]; + float mat_from[4][4]; + quat_to_mat4(mat_from, quat_from); - // Calculate the difference matrix matd between mat_from and mat_to - invert_m4_m4(mati, mat_from); - mul_m4_m4m4(matd, mati, mat_to); + // Calculate the difference matrix matd between mat_from and mat_to + invert_m4_m4(mati, mat_from); + mul_m4_m4m4(matd, mati, mat_to); - mat4_to_quat(qd, matd); + mat4_to_quat(qd, matd); - mul_qt_qtqt(quat_to, qd, quat_from); // rot is the final rotation corresponding to mat_to + mul_qt_qtqt(quat_to, qd, quat_from); // rot is the final rotation corresponding to mat_to } void bc_triangulate_mesh(Mesh *me) { - bool use_beauty = false; - bool tag_only = false; - int quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE; /* XXX: The triangulation method selection could be offered in the UI */ + bool use_beauty = false; + bool tag_only = false; + int quad_method = + MOD_TRIANGULATE_QUAD_SHORTEDGE; /* XXX: The triangulation method selection could be offered in the UI */ - const struct BMeshCreateParams bm_create_params = {0}; - BMesh *bm = BM_mesh_create( - &bm_mesh_allocsize_default, - &bm_create_params); - BMeshFromMeshParams bm_from_me_params = {0}; - bm_from_me_params.calc_face_normal = true; - BM_mesh_bm_from_me(bm, me, &bm_from_me_params); - BM_mesh_triangulate(bm, quad_method, use_beauty, 4, tag_only, NULL, NULL, NULL); + const struct BMeshCreateParams bm_create_params = {0}; + BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_create_params); + BMeshFromMeshParams bm_from_me_params = {0}; + bm_from_me_params.calc_face_normal = true; + BM_mesh_bm_from_me(bm, me, &bm_from_me_params); + BM_mesh_triangulate(bm, quad_method, use_beauty, 4, tag_only, NULL, NULL, NULL); - BMeshToMeshParams bm_to_me_params = {0}; - bm_to_me_params.calc_object_remap = false; - BM_mesh_bm_to_me(NULL, bm, me, &bm_to_me_params); - BM_mesh_free(bm); + BMeshToMeshParams bm_to_me_params = {0}; + bm_to_me_params.calc_object_remap = false; + BM_mesh_bm_to_me(NULL, bm, me, &bm_to_me_params); + BM_mesh_free(bm); } /* @@ -559,39 +559,39 @@ void bc_triangulate_mesh(Mesh *me) */ bool bc_is_leaf_bone(Bone *bone) { - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - if (child->flag & BONE_CONNECTED) - return false; - } - return true; + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + if (child->flag & BONE_CONNECTED) + return false; + } + return true; } -EditBone *bc_get_edit_bone(bArmature * armature, char *name) { - EditBone *eBone; - - for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) { - if (STREQ(name, eBone->name)) - return eBone; - } +EditBone *bc_get_edit_bone(bArmature *armature, char *name) +{ + EditBone *eBone; - return NULL; + for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) { + if (STREQ(name, eBone->name)) + return eBone; + } + return NULL; } int bc_set_layer(int bitfield, int layer) { - return bc_set_layer(bitfield, layer, true); /* enable */ + return bc_set_layer(bitfield, layer, true); /* enable */ } int bc_set_layer(int bitfield, int layer, bool enable) { - int bit = 1u << layer; + int bit = 1u << layer; - if (enable) - bitfield |= bit; - else - bitfield &= ~bit; + if (enable) + bitfield |= bit; + else + bitfield &= ~bit; - return bitfield; + return bitfield; } /** @@ -601,29 +601,29 @@ int bc_set_layer(int bitfield, int layer, bool enable) */ BoneExtensionMap &BoneExtensionManager::getExtensionMap(bArmature *armature) { - std::string key = armature->id.name; - BoneExtensionMap *result = extended_bone_maps[key]; - if (result == NULL) - { - result = new BoneExtensionMap(); - extended_bone_maps[key] = result; - } - return *result; + std::string key = armature->id.name; + BoneExtensionMap *result = extended_bone_maps[key]; + if (result == NULL) { + result = new BoneExtensionMap(); + extended_bone_maps[key] = result; + } + return *result; } BoneExtensionManager::~BoneExtensionManager() { - std::map<std::string, BoneExtensionMap *>::iterator map_it; - for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it) - { - BoneExtensionMap *extended_bones = map_it->second; - for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); ext_it != extended_bones->end(); ++ext_it) { - if (ext_it->second != NULL) - delete ext_it->second; - } - extended_bones->clear(); - delete extended_bones; - } + std::map<std::string, BoneExtensionMap *>::iterator map_it; + for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it) { + BoneExtensionMap *extended_bones = map_it->second; + for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); + ext_it != extended_bones->end(); + ++ext_it) { + if (ext_it->second != NULL) + delete ext_it->second; + } + extended_bones->clear(); + delete extended_bones; + } } /** @@ -634,165 +634,163 @@ BoneExtensionManager::~BoneExtensionManager() BoneExtended::BoneExtended(EditBone *aBone) { - this->set_name(aBone->name); - this->chain_length = 0; - this->is_leaf = false; - this->tail[0] = 0.0f; - this->tail[1] = 0.5f; - this->tail[2] = 0.0f; - this->use_connect = -1; - this->roll = 0; - this->bone_layers = 0; + this->set_name(aBone->name); + this->chain_length = 0; + this->is_leaf = false; + this->tail[0] = 0.0f; + this->tail[1] = 0.5f; + this->tail[2] = 0.0f; + this->use_connect = -1; + this->roll = 0; + this->bone_layers = 0; - this->has_custom_tail = false; - this->has_custom_roll = false; + this->has_custom_tail = false; + this->has_custom_roll = false; } char *BoneExtended::get_name() { - return name; + return name; } void BoneExtended::set_name(char *aName) { - BLI_strncpy(name, aName, MAXBONENAME); + BLI_strncpy(name, aName, MAXBONENAME); } int BoneExtended::get_chain_length() { - return chain_length; + return chain_length; } void BoneExtended::set_chain_length(const int aLength) { - chain_length = aLength; + chain_length = aLength; } void BoneExtended::set_leaf_bone(bool state) { - is_leaf = state; + is_leaf = state; } bool BoneExtended::is_leaf_bone() { - return is_leaf; + return is_leaf; } void BoneExtended::set_roll(float roll) { - this->roll = roll; - this->has_custom_roll = true; + this->roll = roll; + this->has_custom_roll = true; } bool BoneExtended::has_roll() { - return this->has_custom_roll; + return this->has_custom_roll; } float BoneExtended::get_roll() { - return this->roll; + return this->roll; } void BoneExtended::set_tail(float vec[]) { - this->tail[0] = vec[0]; - this->tail[1] = vec[1]; - this->tail[2] = vec[2]; - this->has_custom_tail = true; + this->tail[0] = vec[0]; + this->tail[1] = vec[1]; + this->tail[2] = vec[2]; + this->has_custom_tail = true; } bool BoneExtended::has_tail() { - return this->has_custom_tail; + return this->has_custom_tail; } float *BoneExtended::get_tail() { - return this->tail; + return this->tail; } -inline bool isInteger(const std::string & s) +inline bool isInteger(const std::string &s) { - if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false; + if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) + return false; - char *p; - strtol(s.c_str(), &p, 10); + char *p; + strtol(s.c_str(), &p, 10); - return (*p == 0); + return (*p == 0); } void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels) { - std::stringstream ss(layerString); - std::string layer; - int pos; - - while (ss >> layer) { - - /* Blender uses numbers to specify layers*/ - if (isInteger(layer)) - { - pos = atoi(layer.c_str()); - if (pos >= 0 && pos < 32) { - this->bone_layers = bc_set_layer(this->bone_layers, pos); - continue; - } - } - - /* layer uses labels (not supported by blender). Map to layer numbers:*/ - pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin(); - if (pos >= layer_labels.size()) { - layer_labels.push_back(layer); /* remember layer number for future usage*/ - } - - if (pos > 31) - { - fprintf(stderr, "Too many layers in Import. Layer %s mapped to Blender layer 31\n", layer.c_str()); - pos = 31; - } - - /* If numeric layers and labeled layers are used in parallel (unlikely), - * we get a potential mixup. Just leave as is for now. - */ - this->bone_layers = bc_set_layer(this->bone_layers, pos); - - } + std::stringstream ss(layerString); + std::string layer; + int pos; + + while (ss >> layer) { + + /* Blender uses numbers to specify layers*/ + if (isInteger(layer)) { + pos = atoi(layer.c_str()); + if (pos >= 0 && pos < 32) { + this->bone_layers = bc_set_layer(this->bone_layers, pos); + continue; + } + } + + /* layer uses labels (not supported by blender). Map to layer numbers:*/ + pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin(); + if (pos >= layer_labels.size()) { + layer_labels.push_back(layer); /* remember layer number for future usage*/ + } + + if (pos > 31) { + fprintf(stderr, + "Too many layers in Import. Layer %s mapped to Blender layer 31\n", + layer.c_str()); + pos = 31; + } + + /* If numeric layers and labeled layers are used in parallel (unlikely), + * we get a potential mixup. Just leave as is for now. + */ + this->bone_layers = bc_set_layer(this->bone_layers, pos); + } } std::string BoneExtended::get_bone_layers(int bitfield) { - std::string result = ""; - std::string sep = ""; - int bit = 1u; + std::string result = ""; + std::string sep = ""; + int bit = 1u; - std::ostringstream ss; - for (int i = 0; i < 32; i++) - { - if (bit & bitfield) - { - ss << sep << i; - sep = " "; - } - bit = bit << 1; - } - return ss.str(); + std::ostringstream ss; + for (int i = 0; i < 32; i++) { + if (bit & bitfield) { + ss << sep << i; + sep = " "; + } + bit = bit << 1; + } + return ss.str(); } int BoneExtended::get_bone_layers() { - return (bone_layers == 0) ? 1 : bone_layers; // ensure that the bone is in at least one bone layer! + return (bone_layers == 0) ? 1 : + bone_layers; // ensure that the bone is in at least one bone layer! } - void BoneExtended::set_use_connect(int use_connect) { - this->use_connect = use_connect; + this->use_connect = use_connect; } int BoneExtended::get_use_connect() { - return this->use_connect; + return this->use_connect; } /** @@ -800,25 +798,24 @@ int BoneExtended::get_use_connect() */ void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]) { - IDProperty *idgroup = (IDProperty *)ebone->prop; - if (idgroup == NULL) - { - IDPropertyTemplate val = { 0 }; - idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); - ebone->prop = idgroup; - } + IDProperty *idgroup = (IDProperty *)ebone->prop; + if (idgroup == NULL) { + IDPropertyTemplate val = {0}; + idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + ebone->prop = idgroup; + } - IDPropertyTemplate val = { 0 }; - val.array.len = 16; - val.array.type = IDP_FLOAT; + IDPropertyTemplate val = {0}; + val.array.len = 16; + val.array.type = IDP_FLOAT; - IDProperty *data = IDP_New(IDP_ARRAY, &val, key); - float *array = (float *)IDP_Array(data); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - array[4 * i + j] = mat[i][j]; + IDProperty *data = IDP_New(IDP_ARRAY, &val, key); + float *array = (float *)IDP_Array(data); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + array[4 * i + j] = mat[i][j]; - IDP_AddToGroup(idgroup, data); + IDP_AddToGroup(idgroup, data); } #if 0 @@ -829,17 +826,17 @@ void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]) */ static void bc_set_IDProperty(EditBone *ebone, const char *key, float value) { - if (ebone->prop == NULL) - { - IDPropertyTemplate val = { 0 }; - ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); - } + if (ebone->prop == NULL) + { + IDPropertyTemplate val = { 0 }; + ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + } - IDProperty *pgroup = (IDProperty *)ebone->prop; - IDPropertyTemplate val = { 0 }; - IDProperty *prop = IDP_New(IDP_FLOAT, &val, key); - IDP_Float(prop) = value; - IDP_AddToGroup(pgroup, prop); + IDProperty *pgroup = (IDProperty *)ebone->prop; + IDPropertyTemplate val = { 0 }; + IDProperty *prop = IDP_New(IDP_FLOAT, &val, key); + IDP_Float(prop) = value; + IDP_AddToGroup(pgroup, prop); } #endif @@ -850,7 +847,7 @@ static void bc_set_IDProperty(EditBone *ebone, const char *key, float value) */ IDProperty *bc_get_IDProperty(Bone *bone, std::string key) { - return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str()); + return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str()); } /** @@ -859,24 +856,24 @@ IDProperty *bc_get_IDProperty(Bone *bone, std::string key) */ float bc_get_property(Bone *bone, std::string key, float def) { - float result = def; - IDProperty *property = bc_get_IDProperty(bone, key); - if (property) { - switch (property->type) { - case IDP_INT: - result = (float)(IDP_Int(property)); - break; - case IDP_FLOAT: - result = (float)(IDP_Float(property)); - break; - case IDP_DOUBLE: - result = (float)(IDP_Double(property)); - break; - default: - result = def; - } - } - return result; + float result = def; + IDProperty *property = bc_get_IDProperty(bone, key); + if (property) { + switch (property->type) { + case IDP_INT: + result = (float)(IDP_Int(property)); + break; + case IDP_FLOAT: + result = (float)(IDP_Float(property)); + break; + case IDP_DOUBLE: + result = (float)(IDP_Double(property)); + break; + default: + result = def; + } + } + return result; } /** @@ -889,15 +886,15 @@ float bc_get_property(Bone *bone, std::string key, float def) */ bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]) { - IDProperty *property = bc_get_IDProperty(bone, key); - if (property && property->type == IDP_ARRAY && property->len == 16) { - float *array = (float *)IDP_Array(property); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - mat[i][j] = array[4 * i + j]; - return true; - } - return false; + IDProperty *property = bc_get_IDProperty(bone, key); + if (property && property->type == IDP_ARRAY && property->len == 16) { + float *array = (float *)IDP_Array(property); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = array[4 * i + j]; + return true; + } + return false; } /** @@ -905,9 +902,9 @@ bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]) */ void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]) { - val[0] = bc_get_property(bone, key + "_x", def[0]); - val[1] = bc_get_property(bone, key + "_y", def[1]); - val[2] = bc_get_property(bone, key + "_z", def[2]); + val[0] = bc_get_property(bone, key + "_x", def[0]); + val[1] = bc_get_property(bone, key + "_y", def[1]); + val[2] = bc_get_property(bone, key + "_z", def[2]); } /** @@ -915,139 +912,137 @@ void bc_get_property_vector(Bone *bone, std::string key, float val[3], const flo */ static bool has_custom_props(Bone *bone, bool enabled, std::string key) { - if (!enabled) - return false; - - return (bc_get_IDProperty(bone, key + "_x") - || bc_get_IDProperty(bone, key + "_y") - || bc_get_IDProperty(bone, key + "_z")); + if (!enabled) + return false; + return (bc_get_IDProperty(bone, key + "_x") || bc_get_IDProperty(bone, key + "_y") || + bc_get_IDProperty(bone, key + "_z")); } void bc_enable_fcurves(bAction *act, char *bone_name) { - FCurve *fcu; - char prefix[200]; + FCurve *fcu; + char prefix[200]; - if (bone_name) - BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name); + if (bone_name) + BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name); - for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) { - if (bone_name) { - if (STREQLEN(fcu->rna_path, prefix, strlen(prefix))) - fcu->flag &= ~FCURVE_DISABLED; - else - fcu->flag |= FCURVE_DISABLED; - } - else { - fcu->flag &= ~FCURVE_DISABLED; - } - } + for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) { + if (bone_name) { + if (STREQLEN(fcu->rna_path, prefix, strlen(prefix))) + fcu->flag &= ~FCURVE_DISABLED; + else + fcu->flag |= FCURVE_DISABLED; + } + else { + fcu->flag &= ~FCURVE_DISABLED; + } + } } bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim) { - /* Ok, lets be super cautious and check if the bone exists */ - bPose *pose = ob->pose; - bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name); - if (!pchan) { - return false; - } + /* Ok, lets be super cautious and check if the bone exists */ + bPose *pose = ob->pose; + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name); + if (!pchan) { + return false; + } - bAction *action = bc_getSceneObjectAction(ob); - bPoseChannel *parchan = pchan->parent; + bAction *action = bc_getSceneObjectAction(ob); + bPoseChannel *parchan = pchan->parent; - bc_enable_fcurves(action, bone->name); - float ipar[4][4]; + bc_enable_fcurves(action, bone->name); + float ipar[4][4]; - if (bone->parent) { - invert_m4_m4(ipar, parchan->pose_mat); - mul_m4_m4m4(mat, ipar, pchan->pose_mat); - } - else - copy_m4_m4(mat, pchan->pose_mat); + if (bone->parent) { + invert_m4_m4(ipar, parchan->pose_mat); + mul_m4_m4m4(mat, ipar, pchan->pose_mat); + } + else + copy_m4_m4(mat, pchan->pose_mat); - /* OPEN_SIM_COMPATIBILITY - * AFAIK animation to second life is via BVH, but no - * reason to not have the collada-animation be correct */ - if (for_opensim) { - float temp[4][4]; - copy_m4_m4(temp, bone->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - invert_m4(temp); + /* OPEN_SIM_COMPATIBILITY + * AFAIK animation to second life is via BVH, but no + * reason to not have the collada-animation be correct */ + if (for_opensim) { + float temp[4][4]; + copy_m4_m4(temp, bone->arm_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + invert_m4(temp); - mul_m4_m4m4(mat, mat, temp); + mul_m4_m4m4(mat, mat, temp); - if (bone->parent) { - copy_m4_m4(temp, bone->parent->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + if (bone->parent) { + copy_m4_m4(temp, bone->parent->arm_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - mul_m4_m4m4(mat, temp, mat); - } - } - bc_enable_fcurves(action, NULL); - return true; + mul_m4_m4m4(mat, temp, mat); + } + } + bc_enable_fcurves(action, NULL); + return true; } bool bc_is_animated(BCMatrixSampleMap &values) { - static float MIN_DISTANCE = 0.00001; + static float MIN_DISTANCE = 0.00001; - if (values.size() < 2) - return false; // need at least 2 entries to be not flat + if (values.size() < 2) + return false; // need at least 2 entries to be not flat - BCMatrixSampleMap::iterator it; - const BCMatrix *refmat = NULL; - for (it = values.begin(); it != values.end(); ++it) { - const BCMatrix *matrix = it->second; + BCMatrixSampleMap::iterator it; + const BCMatrix *refmat = NULL; + for (it = values.begin(); it != values.end(); ++it) { + const BCMatrix *matrix = it->second; - if (refmat == NULL) { - refmat = matrix; - continue; - } + if (refmat == NULL) { + refmat = matrix; + continue; + } - if (!matrix->in_range(*refmat, MIN_DISTANCE)) - return true; - } - return false; + if (!matrix->in_range(*refmat, MIN_DISTANCE)) + return true; + } + return false; } bool bc_has_animations(Object *ob) { - /* Check for object, light and camera transform animations */ - if ((bc_getSceneObjectAction(ob) && bc_getSceneObjectAction(ob)->curves.first) || - (bc_getSceneLightAction(ob) && bc_getSceneLightAction(ob)->curves.first) || - (bc_getSceneCameraAction(ob) && bc_getSceneCameraAction(ob)->curves.first)) - return true; + /* Check for object, light and camera transform animations */ + if ((bc_getSceneObjectAction(ob) && bc_getSceneObjectAction(ob)->curves.first) || + (bc_getSceneLightAction(ob) && bc_getSceneLightAction(ob)->curves.first) || + (bc_getSceneCameraAction(ob) && bc_getSceneCameraAction(ob)->curves.first)) + return true; - //Check Material Effect parameter animations. - for (int a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); - if (!ma) continue; - if (ma->adt && ma->adt->action && ma->adt->action->curves.first) - return true; - } + //Check Material Effect parameter animations. + for (int a = 0; a < ob->totcol; a++) { + Material *ma = give_current_material(ob, a + 1); + if (!ma) + continue; + if (ma->adt && ma->adt->action && ma->adt->action->curves.first) + return true; + } - Key *key = BKE_key_from_object(ob); - if ((key && key->adt && key->adt->action) && key->adt->action->curves.first) - return true; + Key *key = BKE_key_from_object(ob); + if ((key && key->adt && key->adt->action) && key->adt->action->curves.first) + return true; - return false; + return false; } - bool bc_has_animations(Scene *sce, LinkNode &export_set) { - LinkNode *node; + LinkNode *node; - for (node = &export_set; node; node = node->next) { - Object *ob = (Object *)node->link; + for (node = &export_set; node; node = node->next) { + Object *ob = (Object *)node->link; - if (bc_has_animations(ob)) - return true; - } - return false; + if (bc_has_animations(ob)) + return true; + } + return false; } /** @@ -1056,56 +1051,58 @@ bool bc_has_animations(Scene *sce, LinkNode &export_set) * * Note: This is old style for Blender <= 2.78 only kept for compatibility */ -void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space) -{ - float loc[3]; - float rot[3]; - float scale[3]; - static const float V0[3] = { 0, 0, 0 }; - - if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") && - !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") && - !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale")) - { - /* No need */ - copy_m4_m4(to_mat, from_mat); - return; - } - - bc_decompose(from_mat, loc, rot, NULL, scale); - loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); - - if (export_settings->keep_bind_info) { - bc_get_property_vector(bone, "restpose_loc", loc, loc); - - if (use_local_space && bone->parent) { - Bone *b = bone; - while (b->parent) { - b = b->parent; - float ploc[3]; - bc_get_property_vector(b, "restpose_loc", ploc, V0); - loc[0] += ploc[0]; - loc[1] += ploc[1]; - loc[2] += ploc[2]; - } - } - } - - if (export_settings->keep_bind_info) { - if (bc_get_IDProperty(bone, "restpose_rot_x")) - rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0)); - if (bc_get_IDProperty(bone, "restpose_rot_y")) - rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0)); - if (bc_get_IDProperty(bone, "restpose_rot_z")) - rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0)); - } - - if (export_settings->keep_bind_info) { - bc_get_property_vector(bone, "restpose_scale", scale, scale); - } - - loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); - +void bc_create_restpose_mat(const ExportSettings *export_settings, + Bone *bone, + float to_mat[4][4], + float from_mat[4][4], + bool use_local_space) +{ + float loc[3]; + float rot[3]; + float scale[3]; + static const float V0[3] = {0, 0, 0}; + + if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale")) { + /* No need */ + copy_m4_m4(to_mat, from_mat); + return; + } + + bc_decompose(from_mat, loc, rot, NULL, scale); + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_loc", loc, loc); + + if (use_local_space && bone->parent) { + Bone *b = bone; + while (b->parent) { + b = b->parent; + float ploc[3]; + bc_get_property_vector(b, "restpose_loc", ploc, V0); + loc[0] += ploc[0]; + loc[1] += ploc[1]; + loc[2] += ploc[2]; + } + } + } + + if (export_settings->keep_bind_info) { + if (bc_get_IDProperty(bone, "restpose_rot_x")) + rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_y")) + rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_z")) + rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0)); + } + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_scale", scale, scale); + } + + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); } /* @@ -1113,74 +1110,74 @@ void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, f */ void bc_sanitize_mat(float mat[4][4], int precision) { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) { - double val = (double)mat[i][j]; - val = double_round(val, precision); - mat[i][j] = (float)val; - } + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) { + double val = (double)mat[i][j]; + val = double_round(val, precision); + mat[i][j] = (float)val; + } } void bc_sanitize_v3(float v[3], int precision) { - for (int i = 0; i < 3; i++) { - double val = (double)v[i]; - val = double_round(val, precision); - v[i] = (float)val; - } + for (int i = 0; i < 3; i++) { + double val = (double)v[i]; + val = double_round(val, precision); + v[i] = (float)val; + } } void bc_sanitize_mat(double mat[4][4], int precision) { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - mat[i][j] = double_round(mat[i][j], precision); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = double_round(mat[i][j], precision); } void bc_sanitize_v3(double v[3], int precision) { - for (int i = 0; i < 3; i++) { - v[i] = double_round(v[i], precision); - } + for (int i = 0; i < 3; i++) { + v[i] = double_round(v[i], precision); + } } void bc_copy_m4_farray(float r[4][4], float *a) { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - r[i][j] = *a++; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + r[i][j] = *a++; } void bc_copy_farray_m4(float *r, float a[4][4]) { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - *r++ = a[i][j]; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + *r++ = a[i][j]; } void bc_copy_darray_m4d(double *r, double a[4][4]) { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - *r++ = a[i][j]; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + *r++ = a[i][j]; } -void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double(&a)[4][4]) +void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double (&a)[4][4]) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - r[i][j] = a[i][j]; - } - } + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r[i][j] = a[i][j]; + } + } } void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - r[i][j] = a[i][j]; - } - } + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r[i][j] = a[i][j]; + } + } } /** @@ -1188,14 +1185,14 @@ void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a) */ std::string bc_get_active_uvlayer_name(Mesh *me) { - int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - if (num_layers) { - char *layer_name = bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV); - if (layer_name) { - return std::string(layer_name); - } - } - return ""; + int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); + if (num_layers) { + char *layer_name = bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV); + if (layer_name) { + return std::string(layer_name); + } + } + return ""; } /** @@ -1204,8 +1201,8 @@ std::string bc_get_active_uvlayer_name(Mesh *me) */ std::string bc_get_active_uvlayer_name(Object *ob) { - Mesh *me = (Mesh *)ob->data; - return bc_get_active_uvlayer_name(me); + Mesh *me = (Mesh *)ob->data; + return bc_get_active_uvlayer_name(me); } /** @@ -1213,205 +1210,205 @@ std::string bc_get_active_uvlayer_name(Object *ob) */ std::string bc_get_uvlayer_name(Mesh *me, int layer) { - int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - if (num_layers && layer < num_layers) { - char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, layer); - if (layer_name) { - return std::string(layer_name); - } - } - return ""; + int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); + if (num_layers && layer < num_layers) { + char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, layer); + if (layer_name) { + return std::string(layer_name); + } + } + return ""; } std::string bc_find_bonename_in_path(std::string path, std::string probe) { - std::string result; - char *boneName = BLI_str_quoted_substrN(path.c_str(), probe.c_str()); - if (boneName) { - result = std::string(boneName); - MEM_freeN(boneName); - } - return result; + std::string result; + char *boneName = BLI_str_quoted_substrN(path.c_str(), probe.c_str()); + if (boneName) { + result = std::string(boneName); + MEM_freeN(boneName); + } + return result; } static bNodeTree *prepare_material_nodetree(Material *ma) { - if (ma->nodetree == NULL) { - ma->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree"); - ma->use_nodes = true; - } - return ma->nodetree; + if (ma->nodetree == NULL) { + ma->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree"); + ma->use_nodes = true; + } + return ma->nodetree; } -bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label) +bNode *bc_add_node( + bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label) { - bNode *node = nodeAddStaticNode(C, ntree, node_type); - if (node) { - if (label.length() > 0) { - strcpy(node->label, label.c_str()); - } - node->locx = locx; - node->locy = locy; - node->flag |= NODE_SELECT; - } - return node; + bNode *node = nodeAddStaticNode(C, ntree, node_type); + if (node) { + if (label.length() > 0) { + strcpy(node->label, label.c_str()); + } + node->locx = locx; + node->locy = locy; + node->flag |= NODE_SELECT; + } + return node; } - bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy) { - return bc_add_node(C, ntree, node_type, locx, locy, ""); + return bc_add_node(C, ntree, node_type, locx, locy, ""); } #if 0 // experimental, probably not used static bNodeSocket *bc_group_add_input_socket(bNodeTree *ntree, bNode *to_node, int to_index, std::string label) { - bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index); + bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index); - //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket); - //return socket; + //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket); + //return socket; - bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket); - bNode *inputGroup = ntreeFindType(ntree, NODE_GROUP_INPUT); - node_group_input_verify(ntree, inputGroup, (ID *)ntree); - bNodeSocket *newsock = node_group_input_find_socket(inputGroup, gsock->identifier); - nodeAddLink(ntree, inputGroup, newsock, to_node, to_socket); - strcpy(newsock->name, label.c_str()); - return newsock; + bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket); + bNode *inputGroup = ntreeFindType(ntree, NODE_GROUP_INPUT); + node_group_input_verify(ntree, inputGroup, (ID *)ntree); + bNodeSocket *newsock = node_group_input_find_socket(inputGroup, gsock->identifier); + nodeAddLink(ntree, inputGroup, newsock, to_node, to_socket); + strcpy(newsock->name, label.c_str()); + return newsock; } static bNodeSocket *bc_group_add_output_socket(bNodeTree *ntree, bNode *from_node, int from_index, std::string label) { - bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index); + bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index); - //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket); - //return socket; + //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket); + //return socket; - bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, from_node, from_socket); - bNode *outputGroup = ntreeFindType(ntree, NODE_GROUP_OUTPUT); - node_group_output_verify(ntree, outputGroup, (ID *)ntree); - bNodeSocket *newsock = node_group_output_find_socket(outputGroup, gsock->identifier); - nodeAddLink(ntree, from_node, from_socket, outputGroup, newsock); - strcpy(newsock->name, label.c_str()); - return newsock; + bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, from_node, from_socket); + bNode *outputGroup = ntreeFindType(ntree, NODE_GROUP_OUTPUT); + node_group_output_verify(ntree, outputGroup, (ID *)ntree); + bNodeSocket *newsock = node_group_output_find_socket(outputGroup, gsock->identifier); + nodeAddLink(ntree, from_node, from_socket, outputGroup, newsock); + strcpy(newsock->name, label.c_str()); + return newsock; } void bc_make_group(bContext *C, bNodeTree *ntree, std::map<std::string, bNode *> nmap) { - bNode *gnode = node_group_make_from_selected(C, ntree, "ShaderNodeGroup", "ShaderNodeTree"); - bNodeTree *gtree = (bNodeTree *)gnode->id; + bNode *gnode = node_group_make_from_selected(C, ntree, "ShaderNodeGroup", "ShaderNodeTree"); + bNodeTree *gtree = (bNodeTree *)gnode->id; - bc_group_add_input_socket(gtree, nmap["main"], 0, "Diffuse"); - bc_group_add_input_socket(gtree, nmap["emission"], 0, "Emission"); - bc_group_add_input_socket(gtree, nmap["mix"], 0, "Transparency"); - bc_group_add_input_socket(gtree, nmap["emission"], 1, "Emission"); - bc_group_add_input_socket(gtree, nmap["main"], 4, "Metallic"); - bc_group_add_input_socket(gtree, nmap["main"], 5, "Specular"); + bc_group_add_input_socket(gtree, nmap["main"], 0, "Diffuse"); + bc_group_add_input_socket(gtree, nmap["emission"], 0, "Emission"); + bc_group_add_input_socket(gtree, nmap["mix"], 0, "Transparency"); + bc_group_add_input_socket(gtree, nmap["emission"], 1, "Emission"); + bc_group_add_input_socket(gtree, nmap["main"], 4, "Metallic"); + bc_group_add_input_socket(gtree, nmap["main"], 5, "Specular"); - bc_group_add_output_socket(gtree, nmap["mix"], 0, "Shader"); + bc_group_add_output_socket(gtree, nmap["mix"], 0, "Shader"); } #endif -static void bc_node_add_link(bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index) +static void bc_node_add_link( + bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index) { - bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index); - bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index); + bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index); + bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index); - nodeAddLink(ntree, from_node, from_socket, to_node, to_socket); + nodeAddLink(ntree, from_node, from_socket, to_node, to_socket); } void bc_add_default_shader(bContext *C, Material *ma) { - bNodeTree *ntree = prepare_material_nodetree(ma); - std::map<std::string, bNode *> nmap; + bNodeTree *ntree = prepare_material_nodetree(ma); + std::map<std::string, bNode *> nmap; #if 0 - nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300); - nmap["emission"] = bc_add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission"); - nmap["add"] = bc_add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400); - nmap["transparent"] = bc_add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200); - nmap["mix"] = bc_add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency"); - nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300); - nmap["out"]->flag &= ~NODE_SELECT; - - bc_node_add_link(ntree, nmap["emission"], 0, nmap["add"], 0); - bc_node_add_link(ntree, nmap["main"], 0, nmap["add"], 1); - bc_node_add_link(ntree, nmap["add"], 0, nmap["mix"], 1); - bc_node_add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2); - - bc_node_add_link(ntree, nmap["mix"], 0, nmap["out"], 0); - // experimental, probably not used. - bc_make_group(C, ntree, nmap); + nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300); + nmap["emission"] = bc_add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission"); + nmap["add"] = bc_add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400); + nmap["transparent"] = bc_add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200); + nmap["mix"] = bc_add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency"); + nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300); + nmap["out"]->flag &= ~NODE_SELECT; + + bc_node_add_link(ntree, nmap["emission"], 0, nmap["add"], 0); + bc_node_add_link(ntree, nmap["main"], 0, nmap["add"], 1); + bc_node_add_link(ntree, nmap["add"], 0, nmap["mix"], 1); + bc_node_add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2); + + bc_node_add_link(ntree, nmap["mix"], 0, nmap["out"], 0); + // experimental, probably not used. + bc_make_group(C, ntree, nmap); #else -nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, 0, 300); -nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 300, 300); -bc_node_add_link(ntree, nmap["main"], 0, nmap["out"], 0); + nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, 0, 300); + nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 300, 300); + bc_node_add_link(ntree, nmap["main"], 0, nmap["out"], 0); #endif } COLLADASW::ColorOrTexture bc_get_base_color(Material *ma) { - bNode *master_shader = bc_get_master_shader(ma); - if (ma->use_nodes && master_shader) { - return bc_get_base_color(master_shader); - } - else { - return bc_get_cot(ma->r, ma->g, ma->b, ma->a); - } + bNode *master_shader = bc_get_master_shader(ma); + if (ma->use_nodes && master_shader) { + return bc_get_base_color(master_shader); + } + else { + return bc_get_cot(ma->r, ma->g, ma->b, ma->a); + } } COLLADASW::ColorOrTexture bc_get_base_color(bNode *shader) { - bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Base Color"); - if (socket) - { - bNodeSocketValueRGBA *dcol = (bNodeSocketValueRGBA *)socket->default_value; - float* col = dcol->value; - return bc_get_cot(col[0], col[1], col[2], col[3]); - } - else { - return bc_get_cot(0.8, 0.8, 0.8, 1.0); //default white - } + bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Base Color"); + if (socket) { + bNodeSocketValueRGBA *dcol = (bNodeSocketValueRGBA *)socket->default_value; + float *col = dcol->value; + return bc_get_cot(col[0], col[1], col[2], col[3]); + } + else { + return bc_get_cot(0.8, 0.8, 0.8, 1.0); //default white + } } bool bc_get_reflectivity(bNode *shader, double &reflectivity) { - bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Specular"); - if (socket) { - bNodeSocketValueFloat *ref = (bNodeSocketValueFloat *)socket->default_value; - reflectivity = (double)ref->value; - return true; - } - return false; + bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Specular"); + if (socket) { + bNodeSocketValueFloat *ref = (bNodeSocketValueFloat *)socket->default_value; + reflectivity = (double)ref->value; + return true; + } + return false; } double bc_get_reflectivity(Material *ma) { - double reflectivity = ma->spec; // fallback if no socket found - bNode *master_shader = bc_get_master_shader(ma); - if (ma->use_nodes && master_shader) { - bc_get_reflectivity(master_shader, reflectivity); - } - return reflectivity; + double reflectivity = ma->spec; // fallback if no socket found + bNode *master_shader = bc_get_master_shader(ma); + if (ma->use_nodes && master_shader) { + bc_get_reflectivity(master_shader, reflectivity); + } + return reflectivity; } bNode *bc_get_master_shader(Material *ma) { - bNodeTree *nodetree = ma->nodetree; - if (nodetree) { - for (bNode *node = (bNode *)nodetree->nodes.first; node; node = node->next) { - if (node->typeinfo->type == SH_NODE_BSDF_PRINCIPLED) { - return node; - } - } - } - return NULL; + bNodeTree *nodetree = ma->nodetree; + if (nodetree) { + for (bNode *node = (bNode *)nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->type == SH_NODE_BSDF_PRINCIPLED) { + return node; + } + } + } + return NULL; } COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a) { - COLLADASW::Color color(r, g, b, a); - COLLADASW::ColorOrTexture cot(color); - return cot; + COLLADASW::Color color(r, g, b, a); + COLLADASW::ColorOrTexture cot(color); + return cot; } diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index b68da4e8154..61b5e306623 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -28,7 +28,6 @@ #include "COLLADASWEffectProfile.h" #include "COLLADAFWColorOrTexture.h" - #include <vector> #include <map> #include <set> @@ -72,9 +71,9 @@ constexpr int LIMITTED_PRECISION = 6; struct Depsgraph; -typedef std::map<COLLADAFW::UniqueId, Image*> UidImageMap; -typedef std::map<std::string, Image*> KeyImageMap; -typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap; +typedef std::map<COLLADAFW::UniqueId, Image *> UidImageMap; +typedef std::map<std::string, Image *> KeyImageMap; +typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *>> TexIndexTextureArrayMap; typedef std::set<Object *> BCObjectSet; extern void bc_update_scene(BlenderContext &blender_context, float ctime); @@ -87,57 +86,64 @@ std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool al inline bAction *bc_getSceneObjectAction(Object *ob) { - return (ob->adt && ob->adt->action) ? ob->adt->action : NULL; + return (ob->adt && ob->adt->action) ? ob->adt->action : NULL; } /* Returns Light Action or NULL */ inline bAction *bc_getSceneLightAction(Object *ob) { - if (ob->type != OB_LAMP) - return NULL; + if (ob->type != OB_LAMP) + return NULL; - Light *lamp = (Light *)ob->data; - return (lamp->adt && lamp->adt->action) ? lamp->adt->action : NULL; + Light *lamp = (Light *)ob->data; + return (lamp->adt && lamp->adt->action) ? lamp->adt->action : NULL; } /* Return Camera Action or NULL */ inline bAction *bc_getSceneCameraAction(Object *ob) { - if (ob->type != OB_CAMERA) - return NULL; + if (ob->type != OB_CAMERA) + return NULL; - Camera *camera = (Camera *)ob->data; - return (camera->adt && camera->adt->action) ? camera->adt->action : NULL; + Camera *camera = (Camera *)ob->data; + return (camera->adt && camera->adt->action) ? camera->adt->action : NULL; } /* returns material action or NULL */ inline bAction *bc_getSceneMaterialAction(Material *ma) { - if (ma == NULL) - return NULL; + if (ma == NULL) + return NULL; - return (ma->adt && ma->adt->action) ? ma->adt->action : NULL; + return (ma->adt && ma->adt->action) ? ma->adt->action : NULL; } inline void bc_setSceneObjectAction(bAction *action, Object *ob) { - if (ob->adt) - ob->adt->action = action; + if (ob->adt) + ob->adt->action = action; } -std::string bc_get_action_id(std::string action_name, std::string ob_name, std::string channel_type, std::string axis_name, std::string axis_separator = "_"); - +std::string bc_get_action_id(std::string action_name, + std::string ob_name, + std::string channel_type, + std::string axis_name, + std::string axis_separator = "_"); -extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index); +extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index); extern int bc_test_parent_loop(Object *par, Object *ob); extern void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer); extern bool bc_validateConstraints(bConstraint *con); extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true); -extern Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name); -extern Mesh *bc_get_mesh_copy( - BlenderContext &blender_context, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate); +extern Object *bc_add_object( + Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name); +extern Mesh *bc_get_mesh_copy(BlenderContext &blender_context, + Object *ob, + BC_export_mesh_type export_mesh_type, + bool apply_modifiers, + bool triangulate); extern Object *bc_get_assigned_armature(Object *ob); extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob); @@ -154,56 +160,63 @@ extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int typ extern void bc_bubble_sort_by_Object_name(LinkNode *export_set); extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only); -extern int bc_get_active_UVLayer(Object *ob); +extern int bc_get_active_UVLayer(Object *ob); std::string bc_find_bonename_in_path(std::string path, std::string probe); -inline std::string bc_string_after(const std::string& s, const char c) +inline std::string bc_string_after(const std::string &s, const char c) { - size_t i = s.rfind(c, s.length()); - if (i != std::string::npos) { - return(s.substr(i + 1, s.length() - i)); - } - return(s); + size_t i = s.rfind(c, s.length()); + if (i != std::string::npos) { + return (s.substr(i + 1, s.length() - i)); + } + return (s); } -inline bool bc_startswith(std::string const & value, std::string const & starting) +inline bool bc_startswith(std::string const &value, std::string const &starting) { - if (starting.size() > value.size()) - return false; - return (value.substr(0, starting.size()) == starting); + if (starting.size() > value.size()) + return false; + return (value.substr(0, starting.size()) == starting); } -#if 0 /* UNUSED */ +#if 0 /* UNUSED */ inline bool bc_endswith(std::string const & value, std::string const & ending) { - if (ending.size() > value.size()) return false; - return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); } #endif -extern std::string bc_replace_string(std::string data, const std::string& pattern, const std::string& replacement); +extern std::string bc_replace_string(std::string data, + const std::string &pattern, + const std::string &replacement); extern std::string bc_url_encode(std::string data); extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene); -extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene); +extern void bc_match_scale(std::vector<Object *> *objects_done, + UnitConverter &unit_converter, + bool scale_to_scene); extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size); -extern void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4]); +extern void bc_rotate_from_reference_quat(float quat_to[4], + float quat_from[4], + float mat_to[4][4]); extern void bc_triangulate_mesh(Mesh *me); extern bool bc_is_leaf_bone(Bone *bone); -extern EditBone *bc_get_edit_bone(bArmature * armature, char *name); +extern EditBone *bc_get_edit_bone(bArmature *armature, char *name); extern int bc_set_layer(int bitfield, int layer, bool enable); extern int bc_set_layer(int bitfield, int layer); -inline bool bc_in_range(float a, float b, float range) { - return fabsf(a - b) < range; +inline bool bc_in_range(float a, float b, float range) +{ + return fabsf(a - b) < range; } void bc_copy_m4_farray(float r[4][4], float *a); void bc_copy_farray_m4(float *r, float a[4][4]); void bc_copy_darray_m4d(double *r, double a[4][4]); -void bc_copy_m4d_v44(double(&r)[4][4], std::vector<std::vector<double>> &a); -void bc_copy_v44_m4d(std::vector<std::vector<double>> &a, double(&r)[4][4]); +void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a); +void bc_copy_v44_m4d(std::vector<std::vector<double>> &a, double (&r)[4][4]); void bc_sanitize_mat(float mat[4][4], int precision); void bc_sanitize_mat(double mat[4][4], int precision); @@ -224,66 +237,67 @@ extern bool bc_is_animated(BCMatrixSampleMap &values); extern bool bc_has_animations(Scene *sce, LinkNode &node); extern bool bc_has_animations(Object *ob); - -extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space); - -class BCPolygonNormalsIndices -{ - std::vector<unsigned int> normal_indices; - - public: - - void add_index(unsigned int index) { - normal_indices.push_back(index); - } - - unsigned int operator[](unsigned int i) { - return normal_indices[i]; - } - +extern void bc_create_restpose_mat(const ExportSettings *export_settings, + Bone *bone, + float to_mat[4][4], + float world[4][4], + bool use_local_space); + +class BCPolygonNormalsIndices { + std::vector<unsigned int> normal_indices; + + public: + void add_index(unsigned int index) + { + normal_indices.push_back(index); + } + + unsigned int operator[](unsigned int i) + { + return normal_indices[i]; + } }; class BoneExtended { -private: - char name[MAXBONENAME]; - int chain_length; - bool is_leaf; - float tail[3]; - float roll; - - int bone_layers; - int use_connect; - bool has_custom_tail; - bool has_custom_roll; + private: + char name[MAXBONENAME]; + int chain_length; + bool is_leaf; + float tail[3]; + float roll; -public: + int bone_layers; + int use_connect; + bool has_custom_tail; + bool has_custom_roll; - BoneExtended(EditBone *aBone); + public: + BoneExtended(EditBone *aBone); - void set_name(char *aName); - char *get_name(); + void set_name(char *aName); + char *get_name(); - void set_chain_length(const int aLength); - int get_chain_length(); + void set_chain_length(const int aLength); + int get_chain_length(); - void set_leaf_bone(bool state); - bool is_leaf_bone(); + void set_leaf_bone(bool state); + bool is_leaf_bone(); - void set_bone_layers(std::string layers, std::vector<std::string> &layer_labels); - int get_bone_layers(); - static std::string get_bone_layers(int bitfield); + void set_bone_layers(std::string layers, std::vector<std::string> &layer_labels); + int get_bone_layers(); + static std::string get_bone_layers(int bitfield); - void set_roll(float roll); - bool has_roll(); - float get_roll(); + void set_roll(float roll); + bool has_roll(); + float get_roll(); - void set_tail(float *vec); - float *get_tail(); - bool has_tail(); + void set_tail(float *vec); + float *get_tail(); + bool has_tail(); - void set_use_connect(int use_connect); - int get_use_connect(); + void set_use_connect(int use_connect); + int get_use_connect(); }; /* a map to store bone extension maps @@ -298,12 +312,12 @@ typedef std::map<std::string, BoneExtended *> BoneExtensionMap; * separate armatures. */ class BoneExtensionManager { -private: - std::map<std::string, BoneExtensionMap *> extended_bone_maps; + private: + std::map<std::string, BoneExtensionMap *> extended_bone_maps; -public: - BoneExtensionMap &getExtensionMap(bArmature *armature); - ~BoneExtensionManager(); + public: + BoneExtensionMap &getExtensionMap(bArmature *armature); + ~BoneExtensionManager(); }; void bc_add_default_shader(bContext *C, Material *ma); |