doxygen: add newline after \file
[blender.git] / source / blender / collada / collada_internal.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup collada
19  */
20
21
22 /* COLLADABU_ASSERT, may be able to remove later */
23 #include "COLLADABUPlatform.h"
24 #include "collada_utils.h"
25
26 #include "BLI_linklist.h"
27 #include "ED_armature.h"
28
29 UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP)
30 {
31         axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI);
32         axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI);
33
34         unit_m4(z_up_mat4);
35         unit_m4(scale_mat4);
36 }
37
38 void UnitConverter::read_asset(const COLLADAFW::FileInfo *asset)
39 {
40         unit = asset->getUnit();
41         up_axis = asset->getUpAxisType();
42 }
43
44 UnitConverter::UnitSystem UnitConverter::isMetricSystem()
45 {
46         switch (unit.getLinearUnitUnit()) {
47                 case COLLADAFW::FileInfo::Unit::MILLIMETER:
48                 case COLLADAFW::FileInfo::Unit::CENTIMETER:
49                 case COLLADAFW::FileInfo::Unit::DECIMETER:
50                 case COLLADAFW::FileInfo::Unit::METER:
51                 case COLLADAFW::FileInfo::Unit::KILOMETER:
52                         return UnitConverter::Metric;
53                 case COLLADAFW::FileInfo::Unit::INCH:
54                 case COLLADAFW::FileInfo::Unit::FOOT:
55                 case COLLADAFW::FileInfo::Unit::YARD:
56                         return UnitConverter::Imperial;
57                 default:
58                         return UnitConverter::None;
59         }
60 }
61
62 float UnitConverter::getLinearMeter()
63 {
64         return (float)unit.getLinearUnitMeter();
65 }
66
67 void UnitConverter::convertVector3(COLLADABU::Math::Vector3 &vec, float *v)
68 {
69         v[0] = vec.x;
70         v[1] = vec.y;
71         v[2] = vec.z;
72 }
73
74 // TODO need also for angle conversion, time conversion...
75
76 void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4& in)
77 {
78         // in DAE, matrices use columns vectors, (see comments in COLLADABUMathMatrix4.h)
79         // so here, to make a blender matrix, we swap columns and rows
80         for (int i = 0; i < 4; i++) {
81                 for (int j = 0; j < 4; j++) {
82                         out[i][j] = in[j][i];
83                 }
84         }
85 }
86
87 void UnitConverter::mat4_to_dae(float out[4][4], float in[4][4])
88 {
89         transpose_m4_m4(out, in);
90 }
91
92 void UnitConverter::mat4_to_dae_double(double out[4][4], float in[4][4])
93 {
94         float mat[4][4];
95
96         mat4_to_dae(mat, in);
97
98         for (int i = 0; i < 4; i++)
99                 for (int j = 0; j < 4; j++)
100                         out[i][j] = mat[i][j];
101 }
102
103 float(&UnitConverter::get_rotation())[4][4]
104 {
105         switch (up_axis) {
106                 case COLLADAFW::FileInfo::X_UP:
107                         return x_up_mat4;
108                         break;
109                 case COLLADAFW::FileInfo::Y_UP:
110                         return y_up_mat4;
111                         break;
112                 default:
113                         return z_up_mat4;
114                         break;
115         }
116 }
117
118
119 float(&UnitConverter::get_scale())[4][4]
120 {
121         return scale_mat4;
122 }
123
124 void UnitConverter::calculate_scale(Scene &sce)
125 {
126         PointerRNA scene_ptr, unit_settings;
127         PropertyRNA *system_ptr, *scale_ptr;
128         RNA_id_pointer_create(&sce.id, &scene_ptr);
129
130         unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings");
131         system_ptr    = RNA_struct_find_property(&unit_settings, "system");
132         scale_ptr     = RNA_struct_find_property(&unit_settings, "scale_length");
133
134         int   type    = RNA_property_enum_get(&unit_settings, system_ptr);
135
136         float bl_scale;
137
138         switch (type) {
139                 case USER_UNIT_NONE:
140                         bl_scale = 1.0; // map 1 Blender unit to 1 Meter
141                         break;
142
143                 case USER_UNIT_METRIC:
144                         bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
145                         break;
146
147                 default :
148                         bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
149                         // it looks like the conversion to Imperial is done implicitly.
150                         // So nothing to do here.
151                         break;
152         }
153
154         float rescale[3];
155         rescale[0] = rescale[1] = rescale[2] = getLinearMeter() / bl_scale;
156
157         size_to_mat4(scale_mat4, rescale);
158 }
159
160 /**
161  * Translation map.
162  * Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
163  * included. Look at the IDREF XSD declaration for more.
164  * Follows strictly the COLLADA XSD declaration which explicitly allows non-english chars,
165  * like special chars (e.g. micro sign), umlauts and so on.
166  * The COLLADA spec also allows additional chars for member access ('.'), these
167  * must obviously be removed too, otherwise they would be heavily misinterpreted.
168  */
169 const unsigned char translate_start_name_map[256] = {
170
171         95, 95, 95, 95, 95, 95, 95, 95,
172         95, 95, 95, 95, 95, 95, 95, 95,
173         95, 95, 95, 95, 95, 95, 95, 95,
174         95, 95, 95, 95, 95, 95, 95, 95,
175         95, 95, 95, 95, 95, 95, 95, 95,
176         95, 95, 95, 95, 95, 95, 95, 95,
177         95, 95, 95, 95, 95, 95, 95, 95,
178         95, 95, 95, 95, 95, 95, 95, 95,
179         95, 65, 66, 67, 68, 69, 70, 71,
180         72, 73, 74, 75, 76, 77, 78, 79,
181         80, 81, 82, 83, 84, 85, 86, 87,
182         88, 89, 90, 95, 95, 95, 95, 95,
183         95, 97, 98, 99, 100, 101, 102, 103,
184         104, 105, 106, 107, 108, 109, 110, 111,
185         112, 113, 114, 115, 116, 117, 118, 119,
186         120, 121, 122, 95, 95, 95, 95, 95,
187
188         128, 129, 130, 131, 132, 133, 134, 135,
189         136, 137, 138, 139, 140, 141, 142, 143,
190         144, 145, 146, 147, 148, 149, 150, 151,
191         152, 153, 154, 155, 156, 157, 158, 159,
192         160, 161, 162, 163, 164, 165, 166, 167,
193         168, 169, 170, 171, 172, 173, 174, 175,
194         176, 177, 178, 179, 180, 181, 182, 183,
195         184, 185, 186, 187, 188, 189, 190, 191,
196         192, 193, 194, 195, 196, 197, 198, 199,
197         200, 201, 202, 203, 204, 205, 206, 207,
198         208, 209, 210, 211, 212, 213, 214, 215,
199         216, 217, 218, 219, 220, 221, 222, 223,
200         224, 225, 226, 227, 228, 229, 230, 231,
201         232, 233, 234, 235, 236, 237, 238, 239,
202         240, 241, 242, 243, 244, 245, 246, 247,
203         248, 249, 250, 251, 252, 253, 254, 255,
204 };
205
206 const unsigned char translate_name_map[256] = {
207
208         95, 95, 95, 95, 95, 95, 95, 95,
209         95, 95, 95, 95, 95, 95, 95, 95,
210         95, 95, 95, 95, 95, 95, 95, 95,
211         95, 95, 95, 95, 95, 95, 95, 95,
212         95, 95, 95, 95, 95, 95, 95, 95,
213         95, 95, 95, 95, 95, 45, 95, 95,
214         48, 49, 50, 51, 52, 53, 54, 55,
215         56, 57, 95, 95, 95, 95, 95, 95,
216         95, 65, 66, 67, 68, 69, 70, 71,
217         72, 73, 74, 75, 76, 77, 78, 79,
218         80, 81, 82, 83, 84, 85, 86, 87,
219         88, 89, 90, 95, 95, 95, 95, 95,
220         95, 97, 98, 99, 100, 101, 102, 103,
221         104, 105, 106, 107, 108, 109, 110, 111,
222         112, 113, 114, 115, 116, 117, 118, 119,
223         120, 121, 122, 95, 95, 95, 95, 95,
224
225         128, 129, 130, 131, 132, 133, 134, 135,
226         136, 137, 138, 139, 140, 141, 142, 143,
227         144, 145, 146, 147, 148, 149, 150, 151,
228         152, 153, 154, 155, 156, 157, 158, 159,
229         160, 161, 162, 163, 164, 165, 166, 167,
230         168, 169, 170, 171, 172, 173, 174, 175,
231         176, 177, 178, 179, 180, 181, 182, 183,
232         184, 185, 186, 187, 188, 189, 190, 191,
233         192, 193, 194, 195, 196, 197, 198, 199,
234         200, 201, 202, 203, 204, 205, 206, 207,
235         208, 209, 210, 211, 212, 213, 214, 215,
236         216, 217, 218, 219, 220, 221, 222, 223,
237         224, 225, 226, 227, 228, 229, 230, 231,
238         232, 233, 234, 235, 236, 237, 238, 239,
239         240, 241, 242, 243, 244, 245, 246, 247,
240         248, 249, 250, 251, 252, 253, 254, 255,
241 };
242
243 typedef std::map< std::string, std::vector<std::string> > map_string_list;
244 map_string_list global_id_map;
245
246 void clear_global_id_map()
247 {
248         global_id_map.clear();
249 }
250
251 /** Look at documentation of translate_map */
252 std::string translate_id(const char *idString)
253 {
254         std::string id = std::string(idString);
255         return translate_id(id);
256 }
257
258 std::string translate_id(const std::string &id)
259 {
260         if (id.size() == 0) {
261                 return id;
262         }
263
264         std::string id_translated = id;
265         id_translated[0] = translate_start_name_map[(unsigned int)id_translated[0]];
266         for (unsigned int i = 1; i < id_translated.size(); i++) {
267                 id_translated[i] = translate_name_map[(unsigned int)id_translated[i]];
268         }
269         // It's so much workload now, the if () should speed up things.
270         if (id_translated != id) {
271                 // Search duplicates
272                 map_string_list::iterator iter = global_id_map.find(id_translated);
273                 if (iter != global_id_map.end()) {
274                         unsigned int i = 0;
275                         bool found = false;
276                         for (i = 0; i < iter->second.size(); i++) {
277                                 if (id == iter->second[i]) {
278                                         found = true;
279                                         break;
280                                 }
281                         }
282                         bool convert = false;
283                         if (found) {
284                                 if (i > 0) {
285                                         convert = true;
286                                 }
287                         }
288                         else {
289                                 convert = true;
290                                 global_id_map[id_translated].push_back(id);
291                         }
292                         if (convert) {
293                                 std::stringstream out;
294                                 out << ++i;
295                                 id_translated += out.str();
296                         }
297                 }
298                 else { global_id_map[id_translated].push_back(id); }
299         }
300         return id_translated;
301 }
302
303 std::string id_name(void *id)
304 {
305         return ((ID *)id)->name + 2;
306 }
307
308 std::string encode_xml(std::string xml)
309 {
310         const std::map<char, std::string> escape {
311                 {'<' , "&lt;"  },
312                 {'>' , "&gt;"  },
313                 {'"' , "&quot;"},
314                 {'\'', "&apos;"},
315                 {'&' , "&amp;" }
316         };
317
318         std::map<char, std::string>::const_iterator it;
319         std::string encoded_xml = "";
320
321         for (unsigned int i = 0; i < xml.size(); i++) {
322                 char c = xml.at(i);
323                 it = escape.find(c);
324
325                 if (it == escape.end()) {
326                         encoded_xml += c;
327                 }
328                 else {
329                         encoded_xml += it->second;
330                 }
331         }
332         return encoded_xml;
333 }
334
335 std::string get_geometry_id(Object *ob)
336 {
337         return translate_id(id_name(ob->data)) + "-mesh";
338 }
339
340 std::string get_geometry_id(Object *ob, bool use_instantiation)
341 {
342         std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob);
343
344         return translate_id(geom_name) + "-mesh";
345 }
346
347 std::string get_light_id(Object *ob)
348 {
349         return translate_id(id_name(ob)) + "-light";
350 }
351
352 std::string get_joint_sid(Bone *bone)
353 {
354         return translate_id(bone->name);
355 }
356 std::string get_joint_sid(EditBone *bone)
357 {
358         return translate_id(bone->name);
359 }
360
361 std::string get_camera_id(Object *ob)
362 {
363         return translate_id(id_name(ob)) + "-camera";
364 }
365
366 std::string get_effect_id(Material *mat)
367 {
368         return translate_id(id_name(mat)) + "-effect";
369 }
370
371 std::string get_material_id(Material *mat)
372 {
373         return translate_id(id_name(mat)) + "-material";
374 }
375
376 std::string get_morph_id(Object *ob)
377 {
378         return translate_id(id_name(ob)) + "-morph";
379 }