00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "math/transform.hpp"
00035 #include "math/quaternion.hpp"
00036 #include "math/units.hpp"
00037 #include "data/string.hpp"
00038 #include "data/list.hpp"
00039
00040 #include <cstring>
00041
00042 namespace gsgl
00043 {
00044
00045 namespace math
00046 {
00047
00048 transform::transform()
00049 : matrix<4,4,gsgl::real_t>()
00050 {
00051 }
00052
00053
00054 transform::transform(const gsgl::real_t *data)
00055 : matrix<4,4,gsgl::real_t>(data)
00056 {
00057 }
00058
00059
00060 transform::transform(const transform & t)
00061 : matrix<4,4,gsgl::real_t>(t)
00062 {
00063 }
00064
00065
00066 transform::transform(const quaternion & q)
00067 {
00068 *this = q;
00069 }
00070
00071
00072 transform::transform(const matrix<4,4,gsgl::real_t> & m)
00073 : matrix<4,4,gsgl::real_t>(m)
00074 {
00075 }
00076
00077
00078 transform & transform::operator= (const transform & t)
00079 {
00080 ::memcpy(data, t.data, 16 * sizeof(gsgl::real_t));
00081 return *this;
00082 }
00083
00084
00085 transform & transform::operator= (const matrix<4,4,gsgl::real_t> & m)
00086 {
00087 ::memcpy(data, m.ptr(), 16 * sizeof(gsgl::real_t));
00088 return *this;
00089 }
00090
00091
00092 transform & transform::operator= (const quaternion & q)
00093 {
00094 data[0] = static_cast<gsgl::real_t>(1 - 2*q.y*q.y - 2*q.z*q.z);
00095 data[1] = static_cast<gsgl::real_t>(2*q.x*q.y + 2*q.w*q.z);
00096 data[2] = static_cast<gsgl::real_t>(2*q.x*q.z - 2*q.w*q.y);
00097 data[3] = 0;
00098
00099 data[4] = static_cast<gsgl::real_t>(2*q.x*q.y - 2*q.w*q.z);
00100 data[5] = static_cast<gsgl::real_t>(1 - 2*q.x*q.x - 2*q.z*q.z);
00101 data[6] = static_cast<gsgl::real_t>(2*q.y*q.z + 2*q.w*q.x);
00102 data[7] = 0;
00103
00104 data[8] = static_cast<gsgl::real_t>(2*q.x*q.z + 2*q.w*q.y);
00105 data[9] = static_cast<gsgl::real_t>(2*q.y*q.z - 2*q.w*q.x);
00106 data[10] = static_cast<gsgl::real_t>(1 - 2*q.x*q.x - 2*q.y*q.y);
00107 data[11] = 0;
00108
00109 data[12] = 0;
00110 data[13] = 0;
00111 data[14] = 0;
00112 data[15] = 1;
00113
00114 return *this;
00115 }
00116
00117
00118 transform::~transform()
00119 {
00120 }
00121
00122
00123
00124
00125 vector transform::translation_part() const
00126 {
00127 return vector(data[12], data[13], data[14]);
00128 }
00129
00130
00131 transform transform::rotation_part() const
00132 {
00133 transform res = IDENTITY;
00134
00135 memcpy(res.data + 0, data + 0, sizeof(gsgl::real_t) * 3);
00136 memcpy(res.data + 4, data + 4, sizeof(gsgl::real_t) * 3);
00137 memcpy(res.data + 8, data + 8, sizeof(gsgl::real_t) * 3);
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 return res;
00152 }
00153
00154
00155
00156 vector transform::get_basis_x() const
00157 {
00158 return vector(data[0], data[1], data[2]);
00159 }
00160
00161
00162 vector transform::get_basis_y() const
00163 {
00164 return vector(data[4], data[5], data[6]);
00165 }
00166
00167
00168 vector transform::get_basis_z() const
00169 {
00170 return vector(data[8], data[9], data[10]);
00171 }
00172
00173
00174 void transform::set_basis_x(const gsgl::real_t & x, const gsgl::real_t & y, const gsgl::real_t & z)
00175 {
00176 data[0] = x;
00177 data[1] = y;
00178 data[2] = z;
00179 }
00180
00181 void transform::set_basis_x(const vector & v)
00182 {
00183 set_basis_x(v.get_x(), v.get_y(), v.get_z());
00184 }
00185
00186
00187 void transform::set_basis_y(const gsgl::real_t & x, const gsgl::real_t & y, const gsgl::real_t & z)
00188 {
00189 data[4] = x;
00190 data[5] = y;
00191 data[6] = z;
00192 }
00193
00194 void transform::set_basis_y(const vector & v)
00195 {
00196 set_basis_y(v.get_x(), v.get_y(), v.get_z());
00197 }
00198
00199
00200 void transform::set_basis_z(const gsgl::real_t & x, const gsgl::real_t & y, const gsgl::real_t & z)
00201 {
00202 data[8] = x;
00203 data[9] = y;
00204 data[10] = z;
00205 }
00206
00207 void transform::set_basis_z(const vector & v)
00208 {
00209 set_basis_z(v.get_x(), v.get_y(), v.get_z());
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 static void invert(float *mat, float *dst)
00225 {
00226 float tmp[12];
00227 float src[16];
00228 float det;
00229
00230
00231 for (int i = 0; i < 4; ++i) {
00232 src[i] = mat[i*4];
00233 src[i + 4] = mat[i*4 + 1];
00234 src[i + 8] = mat[i*4 + 2];
00235 src[i + 12] = mat[i*4 + 3];
00236 }
00237
00238
00239 tmp[0] = src[10] * src[15];
00240 tmp[1] = src[11] * src[14];
00241 tmp[2] = src[9] * src[15];
00242 tmp[3] = src[11] * src[13];
00243 tmp[4] = src[9] * src[14];
00244 tmp[5] = src[10] * src[13];
00245 tmp[6] = src[8] * src[15];
00246 tmp[7] = src[11] * src[12];
00247 tmp[8] = src[8] * src[14];
00248 tmp[9] = src[10] * src[12];
00249 tmp[10] = src[8] * src[13];
00250 tmp[11] = src[9] * src[12];
00251
00252
00253 dst[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
00254 dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
00255 dst[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
00256 dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
00257 dst[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
00258 dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
00259 dst[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
00260 dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
00261 dst[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
00262 dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
00263 dst[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
00264 dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
00265 dst[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
00266 dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
00267 dst[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
00268 dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
00269
00270
00271 tmp[0] = src[2]*src[7];
00272 tmp[1] = src[3]*src[6];
00273 tmp[2] = src[1]*src[7];
00274 tmp[3] = src[3]*src[5];
00275 tmp[4] = src[1]*src[6];
00276 tmp[5] = src[2]*src[5];
00277 tmp[6] = src[0]*src[7];
00278 tmp[7] = src[3]*src[4];
00279 tmp[8] = src[0]*src[6];
00280 tmp[9] = src[2]*src[4];
00281 tmp[10] = src[0]*src[5];
00282 tmp[11] = src[1]*src[4];
00283
00284
00285 dst[8] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
00286 dst[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
00287 dst[9] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
00288 dst[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
00289 dst[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
00290 dst[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
00291 dst[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
00292 dst[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
00293 dst[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
00294 dst[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
00295 dst[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
00296 dst[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
00297 dst[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
00298 dst[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
00299 dst[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
00300 dst[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
00301
00302
00303 det=src[0]*dst[0]+src[1]*dst[1]+src[2]*dst[2]+src[3]*dst[3];
00304
00305
00306 det = 1.0f/det;
00307 for (int j = 0; j < 16; ++j)
00308 dst[j] *= det;
00309 }
00310
00311
00312 transform transform::inverse() const
00313 {
00314 transform res;
00315 invert(const_cast<float *>(this->data), const_cast<float *>(res.data));
00316 return res;
00317 }
00318
00319
00320 transform transform::transpose() const
00321 {
00322 transform res;
00323 for (int i = 0; i < 4; ++i)
00324 for (int j = 0; j < 4; ++j)
00325 res.item(i,j) = this->item(j,i);
00326 return res;
00327 }
00328
00329
00330 transform transform::translation_transform(const vector & v)
00331 {
00332 transform res = IDENTITY;
00333 res.data[12] = v.get_x();
00334 res.data[13] = v.get_y();
00335 res.data[14] = v.get_z();
00336 return res;
00337 }
00338
00339
00340 transform transform::scale(const gsgl::real_t & s)
00341 {
00342 return scale(s, s, s);
00343 }
00344
00345
00346 transform transform::scale(const gsgl::real_t & x, const gsgl::real_t & y, const gsgl::real_t & z)
00347 {
00348 transform res = IDENTITY;
00349 res.data[0] *= x;
00350 res.data[5] *= y;
00351 res.data[10] *= z;
00352 return res;
00353 }
00354
00355
00356 transform transform::parse(const string & str)
00357 {
00358 transform res;
00359
00360 data::list<string> tokens = str.split(L" ,");
00361
00362 int num = 0;
00363 for (data::list<string>::iterator i = tokens.iter(); i.is_valid(); ++i)
00364 {
00365 if (!i->is_empty())
00366 res[num++] = units::parse(*i);
00367 }
00368
00369 return res;
00370 }
00371
00372
00373
00374 static const gsgl::real_t identity_data[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
00375
00376 transform transform::IDENTITY(identity_data);
00377
00378 }
00379
00380 }