Math Lib: add transpose_m3_m3, m3_m4, m4_m4
[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
34 UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP)
35 {
36         unit_m4(x_up_mat4);
37         rotate_m4(x_up_mat4, 'Y', -0.5 * M_PI);
38
39         unit_m4(y_up_mat4);
40         rotate_m4(y_up_mat4, 'X', 0.5 * M_PI);
41
42         unit_m4(z_up_mat4);
43         unit_m4(scale_mat4);
44 }
45
46 void UnitConverter::read_asset(const COLLADAFW::FileInfo *asset)
47 {
48         unit = asset->getUnit();
49         up_axis = asset->getUpAxisType();
50 }
51
52 UnitConverter::UnitSystem UnitConverter::isMetricSystem()
53 {
54         switch (unit.getLinearUnitUnit()) {
55                 case COLLADAFW::FileInfo::Unit::MILLIMETER:
56                 case COLLADAFW::FileInfo::Unit::CENTIMETER:
57                 case COLLADAFW::FileInfo::Unit::DECIMETER:
58                 case COLLADAFW::FileInfo::Unit::METER:
59                 case COLLADAFW::FileInfo::Unit::KILOMETER:
60                         return UnitConverter::Metric;
61                 case COLLADAFW::FileInfo::Unit::INCH:
62                 case COLLADAFW::FileInfo::Unit::FOOT:
63                 case COLLADAFW::FileInfo::Unit::YARD:
64                         return UnitConverter::Imperial;
65                 default:
66                         return UnitConverter::None;
67         }
68 }
69
70 float UnitConverter::getLinearMeter()
71 {
72         return (float)unit.getLinearUnitMeter();
73 }
74
75 void UnitConverter::convertVector3(COLLADABU::Math::Vector3 &vec, float *v)
76 {
77         v[0] = vec.x;
78         v[1] = vec.y;
79         v[2] = vec.z;
80 }
81
82 // TODO need also for angle conversion, time conversion...
83
84 void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4& in)
85 {
86         // in DAE, matrices use columns vectors, (see comments in COLLADABUMathMatrix4.h)
87         // so here, to make a blender matrix, we swap columns and rows
88         for (int i = 0; i < 4; i++) {
89                 for (int j = 0; j < 4; j++) {
90                         out[i][j] = in[j][i];
91                 }
92         }
93 }
94
95 void UnitConverter::mat4_to_dae(float out[4][4], float in[4][4])
96 {
97         transpose_m4_m4(out, in);
98 }
99
100 void UnitConverter::mat4_to_dae_double(double out[4][4], float in[4][4])
101 {
102         float mat[4][4];
103
104         mat4_to_dae(mat, in);
105
106         for (int i = 0; i < 4; i++)
107                 for (int j = 0; j < 4; j++)
108                         out[i][j] = mat[i][j];
109 }
110
111 float(&UnitConverter::get_rotation())[4][4]
112 {
113         switch (up_axis) {
114                 case COLLADAFW::FileInfo::X_UP:
115                         return x_up_mat4;
116                         break;
117                 case COLLADAFW::FileInfo::Y_UP:
118                         return y_up_mat4;
119                         break;
120                 default:
121                         return z_up_mat4;
122                         break;
123         }
124 }
125
126
127 float(&UnitConverter::get_scale())[4][4]
128 {
129         return scale_mat4;
130 }
131
132 void UnitConverter::calculate_scale(Scene &sce)
133 {
134         PointerRNA scene_ptr, unit_settings;
135         PropertyRNA *system_ptr, *scale_ptr;
136         RNA_id_pointer_create(&sce.id, &scene_ptr);
137
138         unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings");
139         system_ptr    = RNA_struct_find_property(&unit_settings, "system");
140         scale_ptr     = RNA_struct_find_property(&unit_settings, "scale_length");
141
142         int   type    = RNA_property_enum_get(&unit_settings, system_ptr);
143
144         float bl_scale;
145
146         switch (type) {
147                 case USER_UNIT_NONE:
148                         bl_scale = 1.0; // map 1 Blender unit to 1 Meter
149                         break;
150
151                 case USER_UNIT_METRIC:
152                         bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
153                         break;
154
155                 default :
156                         bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
157                         // it looks like the conversion to Imperial is done implicitly.
158                         // So nothing to do here.
159                         break;
160         }
161
162         float rescale[3];
163         rescale[0] = rescale[1] = rescale[2] = getLinearMeter() / bl_scale;
164
165         size_to_mat4(scale_mat4, rescale);
166 }
167
168 void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
169 {
170         mat4_to_size(size, mat);
171         if (eul) {
172                 mat4_to_eul(eul, mat);
173         }
174         if (quat) {
175                 mat4_to_quat(quat, mat);
176         }
177         copy_v3_v3(loc, mat[3]);
178 }
179
180 /**
181  * Translation map.
182  * Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
183  * included. Look at the IDREF XSD declaration for more.
184  * Follows strictly the COLLADA XSD declaration which explicitly allows non-english chars,
185  * like special chars (e.g. micro sign), umlauts and so on.
186  * The COLLADA spec also allows additional chars for member access ('.'), these
187  * must obviously be removed too, otherwise they would be heavily misinterpreted.
188  */
189 const unsigned char translate_start_name_map[256] = {
190         95,  95,  95,  95,  95,  95,  95,  95,  95,
191         95,  95,  95,  95,  95,  95,  95,  95,
192         95,  95,  95,  95,  95,  95,  95,  95,
193         95,  95,  95,  95,  95,  95,  95,  95,
194         95,  95,  95,  95,  95,  95,  95,  95,
195         95,  95,  95,  95,  95,  95,  95,  95,
196         95,  95,  95,  95,  95,  95,  95,  95,
197         95,  95,  95,  95,  95,  95,  95,  95,
198         65,  66,  67,  68,  69,  70,  71,  72,
199         73,  74,  75,  76,  77,  78,  79,  80,
200         81,  82,  83,  84,  85,  86,  87,  88,
201         89,  90,  95,  95,  95,  95,  95,  95,
202         97,  98,  99,  100,  101,  102,  103,  104,
203         105,  106,  107,  108,  109,  110,  111,  112,
204         113,  114,  115,  116,  117,  118,  119,  120,
205         121,  122,  95,  95,  95,  95,  95,  95,
206         95,  95,  95,  95,  95,  95,  95,  95,
207         95,  95,  95,  95,  95,  95,  95,  95,
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,  95,  95,  192,
214         193,  194,  195,  196,  197,  198,  199,  200,
215         201,  202,  203,  204,  205,  206,  207,  208,
216         209,  210,  211,  212,  213,  214,  95,  216,
217         217,  218,  219,  220,  221,  222,  223,  224,
218         225,  226,  227,  228,  229,  230,  231,  232,
219         233,  234,  235,  236,  237,  238,  239,  240,
220         241,  242,  243,  244,  245,  246,  95,  248,
221         249,  250,  251,  252,  253,  254,  255
222 };
223
224 const unsigned char translate_name_map[256] = {
225         95,  95,  95,  95,  95,  95,  95,  95,  95,
226         95,  95,  95,  95,  95,  95,  95,  95,
227         95,  95,  95,  95,  95,  95,  95,  95,
228         95,  95,  95,  95,  95,  95,  95,  95,
229         95,  95,  95,  95,  95,  95,  95,  95,
230         95,  95,  95,  95,  45,  95,  95,  48,
231         49,  50,  51,  52,  53,  54,  55,  56,
232         57,  95,  95,  95,  95,  95,  95,  95,
233         65,  66,  67,  68,  69,  70,  71,  72,
234         73,  74,  75,  76,  77,  78,  79,  80,
235         81,  82,  83,  84,  85,  86,  87,  88,
236         89,  90,  95,  95,  95,  95,  95,  95,
237         97,  98,  99,  100,  101,  102,  103,  104,
238         105,  106,  107,  108,  109,  110,  111,  112,
239         113,  114,  115,  116,  117,  118,  119,  120,
240         121,  122,  95,  95,  95,  95,  95,  95,
241         95,  95,  95,  95,  95,  95,  95,  95,
242         95,  95,  95,  95,  95,  95,  95,  95,
243         95,  95,  95,  95,  95,  95,  95,  95,
244         95,  95,  95,  95,  95,  95,  95,  95,
245         95,  95,  95,  95,  95,  95,  95,  95,
246         95,  95,  95,  95,  95,  95,  95,  95,
247         95,  95,  95,  95,  95,  95,  183,  95,
248         95,  95,  95,  95,  95,  95,  95,  192,
249         193,  194,  195,  196,  197,  198,  199,  200,
250         201,  202,  203,  204,  205,  206,  207,  208,
251         209,  210,  211,  212,  213,  214,  95,  216,
252         217,  218,  219,  220,  221,  222,  223,  224,
253         225,  226,  227,  228,  229,  230,  231,  232,
254         233,  234,  235,  236,  237,  238,  239,  240,
255         241,  242,  243,  244,  245,  246,  95,  248,
256         249,  250,  251,  252,  253,  254,  255
257 };
258
259 typedef std::map< std::string, std::vector<std::string> > map_string_list;
260 map_string_list global_id_map;
261
262 void clear_global_id_map()
263 {
264         global_id_map.clear();
265 }
266
267 /** Look at documentation of translate_map */
268 std::string translate_id(const char *idString)
269 {
270         std::string id = std::string(idString);
271         return translate_id(id);
272 }
273
274 std::string translate_id(const std::string &id)
275 {
276         if (id.size() == 0) {
277                 return id;
278         }
279
280         std::string id_translated = id;
281         id_translated[0] = translate_start_name_map[(unsigned int)id_translated[0]];
282         for (unsigned int i = 1; i < id_translated.size(); i++) {
283                 id_translated[i] = translate_name_map[(unsigned int)id_translated[i]];
284         }
285         // It's so much workload now, the if () should speed up things.
286         if (id_translated != id) {
287                 // Search duplicates
288                 map_string_list::iterator iter = global_id_map.find(id_translated);
289                 if (iter != global_id_map.end()) {
290                         unsigned int i = 0;
291                         bool found = false;
292                         for (i = 0; i < iter->second.size(); i++) {
293                                 if (id == iter->second[i]) {
294                                         found = true;
295                                         break;
296                                 }
297                         }
298                         bool convert = false;
299                         if (found) {
300                                 if (i > 0) {
301                                         convert = true;
302                                 }
303                         }
304                         else {
305                                 convert = true;
306                                 global_id_map[id_translated].push_back(id);
307                         }
308                         if (convert) {
309                                 std::stringstream out;
310                                 out << ++i;
311                                 id_translated += out.str();
312                         }
313                 }
314                 else { global_id_map[id_translated].push_back(id); }
315         }
316         return id_translated;
317 }
318
319 std::string id_name(void *id)
320 {
321         return ((ID *)id)->name + 2;
322 }
323
324 std::string get_geometry_id(Object *ob)
325 {
326         return translate_id(id_name(ob->data)) + "-mesh";
327 }
328
329 std::string get_geometry_id(Object *ob, bool use_instantiation)
330 {
331         std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob);
332
333         return translate_id(geom_name) + "-mesh";
334 }
335
336 std::string get_light_id(Object *ob)
337 {
338         return translate_id(id_name(ob)) + "-light";
339 }
340
341 std::string get_joint_id(Bone *bone, Object *ob_arm)
342 {
343         return translate_id(/*id_name(ob_arm) + "_" +*/ bone->name);
344 }
345
346 std::string get_camera_id(Object *ob)
347 {
348         return translate_id(id_name(ob)) + "-camera";
349 }
350
351 std::string get_material_id(Material *mat)
352 {
353         return translate_id(id_name(mat)) + "-material";
354 }
355
356 std::string get_morph_id(Object *ob)
357 {
358         return translate_id(id_name(ob)) + "-morph";
359 }
360