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