c3df2f0dc2fccdc4125ff8487a51067d5ee6e752
[blender-staging.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_internal.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
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         copy_m4_m4(out, in);
98         transpose_m4(out);
99 }
100
101 void UnitConverter::mat4_to_dae_double(double out[4][4], float in[4][4])
102 {
103         float mat[4][4];
104
105         mat4_to_dae(mat, in);
106
107         for (int i = 0; i < 4; i++)
108                 for (int j = 0; j < 4; j++)
109                         out[i][j] = mat[i][j];
110 }
111
112 float(&UnitConverter::get_rotation())[4][4]
113 {
114         switch(up_axis) {
115                 case COLLADAFW::FileInfo::X_UP:
116                         return x_up_mat4;
117                         break;
118                 case COLLADAFW::FileInfo::Y_UP:
119                         return y_up_mat4;
120                         break;
121                 default:
122                         return z_up_mat4;
123                         break;
124         }
125 }
126
127 void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
128 {
129         mat4_to_size(size, mat);
130         if (eul) {
131                 mat4_to_eul(eul, mat);
132         }
133         if (quat) {
134                 mat4_to_quat(quat, mat);
135         }
136         copy_v3_v3(loc, mat[3]);
137 }
138
139 /**
140  * Translation map.
141  * Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
142  * included. Look at the IDREF XSD declaration for more.
143  * Follows strictly the COLLADA XSD declaration which explicitly allows non-english chars,
144  * like special chars (e.g. micro sign), umlauts and so on.
145  * The COLLADA spec also allows additional chars for member access ('.'), these
146  * must obviously be removed too, otherwise they would be heavily misinterpreted.
147  */
148 const unsigned char translate_start_name_map[256] = {
149         95,  95,  95,  95,  95,  95,  95,  95,  95,
150         95,  95,  95,  95,  95,  95,  95,  95,
151         95,  95,  95,  95,  95,  95,  95,  95,
152         95,  95,  95,  95,  95,  95,  95,  95,
153         95,  95,  95,  95,  95,  95,  95,  95,
154         95,  95,  95,  95,  95,  95,  95,  95,
155         95,  95,  95,  95,  95,  95,  95,  95,
156         95,  95,  95,  95,  95,  95,  95,  95,
157         65,  66,  67,  68,  69,  70,  71,  72,
158         73,  74,  75,  76,  77,  78,  79,  80,
159         81,  82,  83,  84,  85,  86,  87,  88,
160         89,  90,  95,  95,  95,  95,  95,  95,
161         97,  98,  99,  100,  101,  102,  103,  104,
162         105,  106,  107,  108,  109,  110,  111,  112,
163         113,  114,  115,  116,  117,  118,  119,  120,
164         121,  122,  95,  95,  95,  95,  95,  95,
165         95,  95,  95,  95,  95,  95,  95,  95,
166         95,  95,  95,  95,  95,  95,  95,  95,
167         95,  95,  95,  95,  95,  95,  95,  95,
168         95,  95,  95,  95,  95,  95,  95,  95,
169         95,  95,  95,  95,  95,  95,  95,  95,
170         95,  95,  95,  95,  95,  95,  95,  95,
171         95,  95,  95,  95,  95,  95,  95,  95,
172         95,  95,  95,  95,  95,  95,  95,  192,
173         193,  194,  195,  196,  197,  198,  199,  200,
174         201,  202,  203,  204,  205,  206,  207,  208,
175         209,  210,  211,  212,  213,  214,  95,  216,
176         217,  218,  219,  220,  221,  222,  223,  224,
177         225,  226,  227,  228,  229,  230,  231,  232,
178         233,  234,  235,  236,  237,  238,  239,  240,
179         241,  242,  243,  244,  245,  246,  95,  248,
180         249,  250,  251,  252,  253,  254,  255
181 };
182
183 const unsigned char translate_name_map[256] = {
184         95,  95,  95,  95,  95,  95,  95,  95,  95,
185         95,  95,  95,  95,  95,  95,  95,  95,
186         95,  95,  95,  95,  95,  95,  95,  95,
187         95,  95,  95,  95,  95,  95,  95,  95,
188         95,  95,  95,  95,  95,  95,  95,  95,
189         95,  95,  95,  95,  45,  95,  95,  48,
190         49,  50,  51,  52,  53,  54,  55,  56,
191         57,  95,  95,  95,  95,  95,  95,  95,
192         65,  66,  67,  68,  69,  70,  71,  72,
193         73,  74,  75,  76,  77,  78,  79,  80,
194         81,  82,  83,  84,  85,  86,  87,  88,
195         89,  90,  95,  95,  95,  95,  95,  95,
196         97,  98,  99,  100,  101,  102,  103,  104,
197         105,  106,  107,  108,  109,  110,  111,  112,
198         113,  114,  115,  116,  117,  118,  119,  120,
199         121,  122,  95,  95,  95,  95,  95,  95,
200         95,  95,  95,  95,  95,  95,  95,  95,
201         95,  95,  95,  95,  95,  95,  95,  95,
202         95,  95,  95,  95,  95,  95,  95,  95,
203         95,  95,  95,  95,  95,  95,  95,  95,
204         95,  95,  95,  95,  95,  95,  95,  95,
205         95,  95,  95,  95,  95,  95,  95,  95,
206         95,  95,  95,  95,  95,  95,  183,  95,
207         95,  95,  95,  95,  95,  95,  95,  192,
208         193,  194,  195,  196,  197,  198,  199,  200,
209         201,  202,  203,  204,  205,  206,  207,  208,
210         209,  210,  211,  212,  213,  214,  95,  216,
211         217,  218,  219,  220,  221,  222,  223,  224,
212         225,  226,  227,  228,  229,  230,  231,  232,
213         233,  234,  235,  236,  237,  238,  239,  240,
214         241,  242,  243,  244,  245,  246,  95,  248,
215         249,  250,  251,  252,  253,  254,  255
216 };
217
218 typedef std::map< std::string, std::vector<std::string> > map_string_list;
219 map_string_list global_id_map;
220
221 void clear_global_id_map()
222 {
223         global_id_map.clear();
224 }
225
226 /** Look at documentation of translate_map */
227 std::string translate_id(const char *idString)
228 {
229         std::string id = std::string(idString);
230         return translate_id(id);
231 }
232
233 std::string translate_id(const std::string &id)
234 {
235         if (id.size() == 0) {
236                 return id;
237         }
238
239         std::string id_translated = id;
240         id_translated[0] = translate_start_name_map[(unsigned int)id_translated[0]];
241         for (unsigned int i = 1; i < id_translated.size(); i++) {
242                 id_translated[i] = translate_name_map[(unsigned int)id_translated[i]];
243         }
244         // It's so much workload now, the if () should speed up things.
245         if (id_translated != id) {
246                 // Search duplicates
247                 map_string_list::iterator iter = global_id_map.find(id_translated);
248                 if (iter != global_id_map.end()) {
249                         unsigned int i = 0;
250                         bool found = false;
251                         for (i = 0; i < iter->second.size(); i++) {
252                                 if (id == iter->second[i]) {
253                                         found = true;
254                                         break;
255                                 }
256                         }
257                         bool convert = false;
258                         if (found) {
259                                 if (i > 0) {
260                                         convert = true;
261                                 }
262                         }
263                         else {
264                                 convert = true;
265                                 global_id_map[id_translated].push_back(id);
266                         }
267                         if (convert) {
268                                 std::stringstream out;
269                                 out << ++i;
270                                 id_translated += out.str();
271                         }
272                 }
273                 else { global_id_map[id_translated].push_back(id); }
274         }
275         return id_translated;
276 }
277
278 std::string id_name(void *id)
279 {
280         return ((ID *)id)->name + 2;
281 }
282
283 std::string get_geometry_id(Object *ob)
284 {
285         return translate_id(id_name(ob->data)) + "-mesh";
286 }
287
288 std::string get_geometry_id(Object *ob, bool use_instantiation)
289 {
290         std::string geom_name = (use_instantiation) ? id_name(ob->data) : id_name(ob);
291
292         return translate_id(geom_name) + "-mesh";
293 }
294
295 std::string get_light_id(Object *ob)
296 {
297         return translate_id(id_name(ob)) + "-light";
298 }
299
300 std::string get_joint_id(Bone *bone, Object *ob_arm)
301 {
302         return translate_id(/*id_name(ob_arm) + "_" +*/ bone->name);
303 }
304
305 std::string get_camera_id(Object *ob)
306 {
307         return translate_id(id_name(ob)) + "-camera";
308 }
309
310 std::string get_material_id(Material *mat)
311 {
312         return translate_id(id_name(mat)) + "-material";
313 }
314
315 std::string get_morph_id(Object *ob)
316 {
317         return translate_id(id_name(ob)) + "-morph";
318 }
319