b3ac62bb6a46d5a5461c5756ad797858fdaf620d
[blender-staging.git] / source / blender / collada / collada_internal.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /* COLLADABU_ASSERT, may be able to remove later */
26 #include "COLLADABUPlatform.h"
27
28 #include "collada_internal.h"
29
30 UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP) {}
31
32 void UnitConverter::read_asset(const COLLADAFW::FileInfo* asset)
33 {
34         unit = asset->getUnit();
35         up_axis = asset->getUpAxisType();
36 }
37
38 UnitConverter::UnitSystem UnitConverter::isMetricSystem()
39 {
40         switch(unit.getLinearUnitUnit()) {
41                 case COLLADAFW::FileInfo::Unit::MILLIMETER:
42                 case COLLADAFW::FileInfo::Unit::CENTIMETER:
43                 case COLLADAFW::FileInfo::Unit::DECIMETER:
44                 case COLLADAFW::FileInfo::Unit::METER:
45                 case COLLADAFW::FileInfo::Unit::KILOMETER:
46                         return UnitConverter::Metric;
47                 case COLLADAFW::FileInfo::Unit::INCH:
48                 case COLLADAFW::FileInfo::Unit::FOOT:
49                 case COLLADAFW::FileInfo::Unit::YARD:
50                         return UnitConverter::Imperial;
51                 default:
52                         return UnitConverter::None;
53         }
54 }
55
56 float UnitConverter::getLinearMeter()
57 {
58         return (float)unit.getLinearUnitMeter();
59 }
60
61 void UnitConverter::convertVector3(COLLADABU::Math::Vector3 &vec, float *v)
62 {
63         v[0] = vec.x;
64         v[1] = vec.y;
65         v[2] = vec.z;
66 }
67
68 // TODO need also for angle conversion, time conversion...
69
70 void UnitConverter::dae_matrix_to_mat4_(float out[][4], const COLLADABU::Math::Matrix4& in)
71 {
72         // in DAE, matrices use columns vectors, (see comments in COLLADABUMathMatrix4.h)
73         // so here, to make a blender matrix, we swap columns and rows
74         for (int i = 0; i < 4; i++) {
75                 for (int j = 0; j < 4; j++) {
76                         out[i][j] = in[j][i];
77                 }
78         }
79 }
80
81 void UnitConverter::mat4_to_dae(float out[][4], float in[][4])
82 {
83         copy_m4_m4(out, in);
84         transpose_m4(out);
85 }
86
87 void UnitConverter::mat4_to_dae_double(double out[][4], float in[][4])
88 {
89         float mat[4][4];
90
91         mat4_to_dae(mat, in);
92
93         for (int i = 0; i < 4; i++)
94                 for (int j = 0; j < 4; j++)
95                         out[i][j] = mat[i][j];
96 }
97
98 void TransformBase::decompose(float mat[][4], float *loc, float eul[3], float quat[4], float *size)
99 {
100         mat4_to_size(size, mat);
101         if (eul) {
102                 mat4_to_eul(eul, mat);
103         }
104         if (quat) {
105                 mat4_to_quat(quat, mat);
106         }
107         copy_v3_v3(loc, mat[3]);
108 }
109
110 /**
111 Translation map.
112 Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
113 included. Look at the IDREF XSD declaration for more.
114 Follows strictly the COLLADA XSD declaration which explicitly allows non-english chars,
115 like special chars (e.g. micro sign), umlauts and so on.
116 The COLLADA spec also allows additional chars for member access ('.'), these
117 must obviously be removed too, otherwise they would be heavily misinterpreted.
118 */
119 const unsigned char translate_start_name_map[256] = {
120 95,  95,  95,  95,  95,  95,  95,  95,  95,
121 95,  95,  95,  95,  95,  95,  95,  95,
122 95,  95,  95,  95,  95,  95,  95,  95,
123 95,  95,  95,  95,  95,  95,  95,  95,
124 95,  95,  95,  95,  95,  95,  95,  95,
125 95,  95,  95,  95,  95,  95,  95,  95,
126 95,  95,  95,  95,  95,  95,  95,  95,
127 95,  95,  95,  95,  95,  95,  95,  95,
128 65,  66,  67,  68,  69,  70,  71,  72,
129 73,  74,  75,  76,  77,  78,  79,  80,
130 81,  82,  83,  84,  85,  86,  87,  88,
131 89,  90,  95,  95,  95,  95,  95,  95,
132 97,  98,  99,  100,  101,  102,  103,  104,
133 105,  106,  107,  108,  109,  110,  111,  112,
134 113,  114,  115,  116,  117,  118,  119,  120,
135 121,  122,  95,  95,  95,  95,  95,  95,
136 95,  95,  95,  95,  95,  95,  95,  95,
137 95,  95,  95,  95,  95,  95,  95,  95,
138 95,  95,  95,  95,  95,  95,  95,  95,
139 95,  95,  95,  95,  95,  95,  95,  95,
140 95,  95,  95,  95,  95,  95,  95,  95,
141 95,  95,  95,  95,  95,  95,  95,  95,
142 95,  95,  95,  95,  95,  95,  95,  95,
143 95,  95,  95,  95,  95,  95,  95,  192,
144 193,  194,  195,  196,  197,  198,  199,  200,
145 201,  202,  203,  204,  205,  206,  207,  208,
146 209,  210,  211,  212,  213,  214,  95,  216,
147 217,  218,  219,  220,  221,  222,  223,  224,
148 225,  226,  227,  228,  229,  230,  231,  232,
149 233,  234,  235,  236,  237,  238,  239,  240,
150 241,  242,  243,  244,  245,  246,  95,  248,
151 249,  250,  251,  252,  253,  254,  255};
152
153 const unsigned char translate_name_map[256] = {
154 95,  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 95,  95,  95,  95,  95,  95,  95,  95,
158 95,  95,  95,  95,  95,  95,  95,  95,
159 95,  95,  95,  95,  45,  95,  95,  48,
160 49,  50,  51,  52,  53,  54,  55,  56,
161 57,  95,  95,  95,  95,  95,  95,  95,
162 65,  66,  67,  68,  69,  70,  71,  72,
163 73,  74,  75,  76,  77,  78,  79,  80,
164 81,  82,  83,  84,  85,  86,  87,  88,
165 89,  90,  95,  95,  95,  95,  95,  95,
166 97,  98,  99,  100,  101,  102,  103,  104,
167 105,  106,  107,  108,  109,  110,  111,  112,
168 113,  114,  115,  116,  117,  118,  119,  120,
169 121,  122,  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,  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,  183,  95,
177 95,  95,  95,  95,  95,  95,  95,  192,
178 193,  194,  195,  196,  197,  198,  199,  200,
179 201,  202,  203,  204,  205,  206,  207,  208,
180 209,  210,  211,  212,  213,  214,  95,  216,
181 217,  218,  219,  220,  221,  222,  223,  224,
182 225,  226,  227,  228,  229,  230,  231,  232,
183 233,  234,  235,  236,  237,  238,  239,  240,
184 241,  242,  243,  244,  245,  246,  95,  248,
185 249,  250,  251,  252,  253,  254,  255};
186
187 typedef std::map< std::string, std::vector<std::string> > map_string_list;
188 map_string_list global_id_map;
189
190 void clear_global_id_map()
191 {
192         global_id_map.clear();
193 }
194
195 /** Look at documentation of translate_map */
196 std::string translate_id(const std::string &id)
197 {
198         if (id.size() == 0)
199         { return id; }
200         std::string id_translated = id;
201         id_translated[0] = translate_start_name_map[(unsigned int)id_translated[0]];
202         for (unsigned int i=1; i < id_translated.size(); i++)
203         {
204                 id_translated[i] = translate_name_map[(unsigned int)id_translated[i]];
205         }
206         // It's so much workload now, the if() should speed up things.
207         if (id_translated != id)
208         {
209                 // Search duplicates
210                 map_string_list::iterator iter = global_id_map.find(id_translated);
211                 if (iter != global_id_map.end())
212                 {
213                         unsigned int i = 0;
214                         bool found = false;
215                         for (i=0; i < iter->second.size(); i++)
216                         {
217                                 if (id == iter->second[i])
218                                 { 
219                                         found = true;
220                                         break;
221                                 }
222                         }
223                         bool convert = false;
224                         if (found)
225                         {
226                           if (i > 0)
227                           { convert = true; }
228                         }
229                         else
230                         { 
231                                 convert = true;
232                                 global_id_map[id_translated].push_back(id);
233                         }
234                         if (convert)
235                         {
236                                 std::stringstream out;
237                                 out << ++i;
238                                 id_translated += out.str();
239                         }
240                 }
241                 else { global_id_map[id_translated].push_back(id); }
242         }
243         return id_translated;
244 }
245
246 std::string id_name(void *id)
247 {
248         return ((ID*)id)->name + 2;
249 }
250
251 std::string get_geometry_id(Object *ob)
252 {
253         return translate_id(id_name(ob->data)) + "-mesh";
254 }
255
256 std::string get_light_id(Object *ob)
257 {
258         return translate_id(id_name(ob)) + "-light";
259 }
260
261 std::string get_joint_id(Bone *bone, Object *ob_arm)
262 {
263         return translate_id(id_name(ob_arm) + "_" + bone->name);
264 }
265
266 std::string get_camera_id(Object *ob)
267 {
268         return translate_id(id_name(ob)) + "-camera";
269 }