/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup collada */ /* COLLADABU_ASSERT, may be able to remove later */ #include "COLLADABUPlatform.h" #include "collada_utils.h" #include "BLI_linklist.h" #include "BKE_armature.h" UnitConverter::UnitConverter() : up_axis(COLLADAFW::FileInfo::Z_UP) { axis_angle_to_mat4_single(x_up_mat4, 'Y', -M_PI_2); axis_angle_to_mat4_single(y_up_mat4, 'X', M_PI_2); unit_m4(z_up_mat4); unit_m4(scale_mat4); } void UnitConverter::read_asset(const COLLADAFW::FileInfo *asset) { 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; } } float UnitConverter::getLinearMeter() { 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; } /* TODO: need also for angle conversion, time conversion... */ 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]; } } } void UnitConverter::mat4_to_dae(float out[4][4], float in[4][4]) { transpose_m4_m4(out, in); } void UnitConverter::mat4_to_dae_double(double out[4][4], float in[4][4]) { float mat[4][4]; 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]; } } } 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; } } float (&UnitConverter::get_scale())[4][4] { 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); 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); float bl_scale; 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; 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; size_to_mat4(scale_mat4, rescale); } /** * Translation map. * Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be * included. Look at the IDREF XSD declaration for more. * Follows strictly the COLLADA XSD declaration which explicitly allows non-English chars, * like special chars (e.g. micro sign), umlauts and so on. * The COLLADA spec also allows additional chars for member access ('.'), these * must obviously be removed too, otherwise they would be heavily misinterpreted. */ const uchar 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, }; const uchar 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, }; using map_string_list = std::map>; map_string_list global_id_map; void clear_global_id_map() { global_id_map.clear(); } std::string translate_id(const char *idString) { std::string id = std::string(idString); return translate_id(id); } std::string translate_id(const std::string &id) { if (id.empty()) { return id; } std::string id_translated = id; id_translated[0] = translate_start_name_map[uint(id_translated[0])]; for (uint i = 1; i < id_translated.size(); i++) { id_translated[i] = translate_name_map[uint(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()) { uint 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; } std::string encode_xml(std::string xml) { const std::map escape{ {'<', "<"}, {'>', ">"}, {'"', """}, {'\'', "'"}, {'&', "&"}}; std::map::const_iterator it; std::string encoded_xml; for (char c : xml) { 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"; } std::string get_geometry_id(Object *ob, bool use_instantiation) { std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob); return translate_id(geom_name) + "-mesh"; } std::string get_light_id(Object *ob) { return translate_id(id_name(ob)) + "-light"; } std::string get_joint_sid(Bone *bone) { return translate_id(bone->name); } static std::string get_joint_sid(EditBone *bone) { return translate_id(bone->name); } std::string get_camera_id(Object *ob) { return translate_id(id_name(ob)) + "-camera"; } std::string get_effect_id(Material *mat) { return translate_id(id_name(mat)) + "-effect"; } std::string get_material_id(Material *mat) { return translate_id(id_name(mat)) + "-material"; } std::string get_morph_id(Object *ob) { return translate_id(id_name(ob)) + "-morph"; }