00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 void
00025 compose_matrix(FLOATNAME(LMatrix3) &mat,
00026 const FLOATNAME(LVecBase3) &scale,
00027 const FLOATNAME(LVecBase3) &hpr,
00028 CoordinateSystem cs) {
00029
00030
00031
00032
00033 if (temp_hpr_fix) {
00034 mat.scale_multiply(scale,
00035 FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::forward(cs), cs) *
00036 FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
00037 FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs));
00038 } else {
00039 mat.scale_multiply(scale,
00040 FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
00041 FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs) *
00042 FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::back(cs), cs));
00043 }
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 static void
00056 unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) {
00057
00058 typedef FLOATNAME(LMatrix3) Matrix;
00059
00060 if (temp_hpr_fix) {
00061
00062 FLOATNAME(LVector3) x, y, z;
00063 mat.get_row(x,0);
00064 mat.get_row(y,1);
00065 mat.get_row(z,2);
00066
00067
00068 FLOATNAME(LVector2) xz(z[0], z[2]);
00069 xz = normalize(xz);
00070
00071
00072
00073 FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xz[0], xz[1])));
00074
00075
00076 Matrix rot_y;
00077 rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00078 CS_yup_right);
00079
00080 x = x * rot_y;
00081 y = y * rot_y;
00082 z = z * rot_y;
00083
00084
00085 FLOATNAME(LVector2) yz(z[1], z[2]);
00086 yz = normalize(yz);
00087
00088
00089 FLOATTYPE pitch = rad_2_deg((FLOATTYPE)(-atan2(yz[0], yz[1])));
00090
00091
00092 Matrix rot_x;
00093 rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00094 CS_yup_right);
00095
00096 x = x * rot_x;
00097 y = y * rot_x;
00098 z = z * rot_x;
00099
00100
00101 FLOATNAME(LVector2) xy(x[0], x[1]);
00102 xy = normalize(xy);
00103
00104
00105 FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00106
00107
00108 Matrix rot_z;
00109 rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00110 CS_yup_right);
00111
00112 x = x * rot_z;
00113 y = y * rot_z;
00114 z = z * rot_z;
00115
00116
00117 mat.set_row(0, x);
00118 mat.set_row(1, y);
00119 mat.set_row(2, z);
00120
00121
00122 hpr[0] = heading;
00123 hpr[1] = pitch;
00124 hpr[2] = roll;
00125 } else {
00126
00127
00128 FLOATNAME(LVector3) x, y, z;
00129 mat.get_row(x,0);
00130 mat.get_row(y,1);
00131 mat.get_row(z,2);
00132
00133
00134 FLOATNAME(LVector2) xy(x[0], x[1]);
00135 xy = normalize(xy);
00136
00137
00138 FLOATTYPE roll = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00139
00140
00141 Matrix rot_z;
00142 rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00143 CS_yup_right);
00144
00145 x = x * rot_z;
00146 y = y * rot_z;
00147 z = z * rot_z;
00148
00149
00150 FLOATNAME(LVector2) xz(x[0], x[2]);
00151 xz = normalize(xz);
00152
00153
00154
00155 FLOATTYPE heading = rad_2_deg(((FLOATTYPE)-atan2(xz[1], xz[0])));
00156
00157
00158 Matrix rot_y;
00159 rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00160 CS_yup_right);
00161
00162 x = x * rot_y;
00163 y = y * rot_y;
00164 z = z * rot_y;
00165
00166
00167 FLOATNAME(LVector2) yz(z[1], z[2]);
00168 yz = normalize(yz);
00169
00170
00171 FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)-atan2(yz[0], yz[1])));
00172
00173
00174 Matrix rot_x;
00175 rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00176 CS_yup_right);
00177
00178 x = x * rot_x;
00179 y = y * rot_x;
00180 z = z * rot_x;
00181
00182
00183 mat.set_row(0, x);
00184 mat.set_row(1, y);
00185 mat.set_row(2, z);
00186
00187
00188 hpr[0] = heading;
00189 hpr[1] = pitch;
00190 hpr[2] = roll;
00191 }
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 static void
00205 unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr,
00206 FLOATTYPE roll) {
00207 if (temp_hpr_fix) {
00208 unwind_yup_rotation(mat, hpr);
00209 return;
00210 }
00211
00212 typedef FLOATNAME(LMatrix3) Matrix;
00213
00214
00215 FLOATNAME(LVector3) x, y, z;
00216 mat.get_row(x,0);
00217 mat.get_row(y,1);
00218 mat.get_row(z,2);
00219
00220
00221 Matrix rot_z;
00222 rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00223 CS_yup_right);
00224
00225 x = x * rot_z;
00226 y = y * rot_z;
00227 z = z * rot_z;
00228
00229
00230 FLOATNAME(LVector2) xz(x[0], x[2]);
00231 xz = normalize(xz);
00232
00233
00234
00235 FLOATTYPE heading = rad_2_deg(((FLOATTYPE)-atan2(xz[1], xz[0])));
00236
00237
00238 Matrix rot_y;
00239 rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00240 CS_yup_right);
00241
00242 x = x * rot_y;
00243 y = y * rot_y;
00244 z = z * rot_y;
00245
00246
00247 FLOATNAME(LVector2) yz(z[1], z[2]);
00248 yz = normalize(yz);
00249
00250
00251 FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)-atan2(yz[0], yz[1])));
00252
00253
00254 Matrix rot_x;
00255 rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00256 CS_yup_right);
00257
00258 x = x * rot_x;
00259 y = y * rot_x;
00260 z = z * rot_x;
00261
00262
00263 mat.set_row(0, x);
00264 mat.set_row(1, y);
00265 mat.set_row(2, z);
00266
00267
00268 hpr[0] = heading;
00269 hpr[1] = pitch;
00270 hpr[2] = roll;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 static void
00283 unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) {
00284 if (temp_hpr_fix) {
00285 typedef FLOATNAME(LMatrix3) Matrix;
00286
00287
00288 FLOATNAME(LVector3) x, y, z;
00289 mat.get_row(x,0);
00290 mat.get_row(y,1);
00291 mat.get_row(z,2);
00292
00293
00294 FLOATNAME(LVector2) xy(y[0], y[1]);
00295 xy = normalize(xy);
00296
00297
00298
00299 FLOATTYPE heading = -rad_2_deg(((FLOATTYPE)atan2(xy[0], xy[1])));
00300
00301
00302 Matrix rot_z;
00303 rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00304 CS_zup_right);
00305
00306 x = x * rot_z;
00307 y = y * rot_z;
00308 z = z * rot_z;
00309
00310
00311 FLOATNAME(LVector2) yz(y[1], y[2]);
00312 yz = normalize(yz);
00313
00314
00315 FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
00316
00317
00318 Matrix rot_x;
00319 rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00320 CS_zup_right);
00321
00322 x = x * rot_x;
00323 y = y * rot_x;
00324 z = z * rot_x;
00325
00326
00327 FLOATNAME(LVector2) xz(x[0], x[2]);
00328 xz = normalize(xz);
00329
00330
00331 FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)atan2(xz[1], xz[0])));
00332
00333
00334 Matrix rot_y;
00335 rot_y = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00336 CS_zup_right);
00337
00338 x = x * rot_y;
00339 y = y * rot_y;
00340 z = z * rot_y;
00341
00342
00343 mat.set_row(0, x);
00344 mat.set_row(1, y);
00345 mat.set_row(2, z);
00346
00347
00348 hpr[0] = heading;
00349 hpr[1] = pitch;
00350 hpr[2] = roll;
00351
00352 } else {
00353 typedef FLOATNAME(LMatrix3) Matrix;
00354
00355
00356 FLOATNAME(LVector3) x, y, z;
00357 mat.get_row(x,0);
00358 mat.get_row(y,1);
00359 mat.get_row(z,2);
00360
00361
00362
00363 FLOATNAME(LVector2) xz(x[0], x[2]);
00364 xz = normalize(xz);
00365
00366
00367 FLOATTYPE roll = rad_2_deg(((FLOATTYPE)atan2(xz[1], xz[0])));
00368
00369 if (y[1] < 0.0f) {
00370 if (roll < 0.0f) {
00371 roll += 180.0;
00372 } else {
00373 roll -= 180.0;
00374 }
00375 }
00376
00377
00378 Matrix rot_y;
00379 rot_y = Matrix::rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00380 CS_zup_right);
00381
00382 x = x * rot_y;
00383 y = y * rot_y;
00384 z = z * rot_y;
00385
00386
00387 FLOATNAME(LVector2) xy(x[0], x[1]);
00388 xy = normalize(xy);
00389
00390
00391
00392 FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00393
00394
00395 Matrix rot_z;
00396 rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00397 CS_zup_right);
00398
00399 x = x * rot_z;
00400 y = y * rot_z;
00401 z = z * rot_z;
00402
00403
00404 FLOATNAME(LVector2) yz(y[1], y[2]);
00405 yz = normalize(yz);
00406
00407
00408 FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
00409
00410
00411 Matrix rot_x;
00412 rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00413 CS_zup_right);
00414
00415 x = x * rot_x;
00416 y = y * rot_x;
00417 z = z * rot_x;
00418
00419
00420 mat.set_row(0, x);
00421 mat.set_row(1, y);
00422 mat.set_row(2, z);
00423
00424
00425 hpr[0] = heading;
00426 hpr[1] = pitch;
00427 hpr[2] = roll;
00428 }
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 static void
00442 unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr,
00443 FLOATTYPE roll) {
00444 if (temp_hpr_fix) {
00445 unwind_zup_rotation(mat, hpr);
00446 return;
00447 }
00448
00449 typedef FLOATNAME(LMatrix3) Matrix;
00450
00451
00452 FLOATNAME(LVector3) x, y, z;
00453 mat.get_row(x,0);
00454 mat.get_row(y,1);
00455 mat.get_row(z,2);
00456
00457
00458 Matrix rot_y;
00459 rot_y = Matrix::rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00460 CS_zup_right);
00461
00462 x = x * rot_y;
00463 y = y * rot_y;
00464 z = z * rot_y;
00465
00466
00467 FLOATNAME(LVector2) xy(x[0], x[1]);
00468 xy = normalize(xy);
00469
00470
00471
00472 FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00473
00474
00475 Matrix rot_z;
00476 rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00477 CS_zup_right);
00478
00479 x = x * rot_z;
00480 y = y * rot_z;
00481 z = z * rot_z;
00482
00483
00484 FLOATNAME(LVector2) yz(y[1], y[2]);
00485 yz = normalize(yz);
00486
00487
00488 FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
00489
00490
00491 Matrix rot_x;
00492 rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00493 CS_zup_right);
00494
00495 x = x * rot_x;
00496 y = y * rot_x;
00497 z = z * rot_x;
00498
00499
00500 mat.set_row(0, x);
00501 mat.set_row(1, y);
00502 mat.set_row(2, z);
00503
00504
00505 hpr[0] = heading;
00506 hpr[1] = pitch;
00507 hpr[2] = roll;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517 bool
00518 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
00519 FLOATNAME(LVecBase3) &scale,
00520 FLOATNAME(LVecBase3) &hpr,
00521 CoordinateSystem cs) {
00522 if (cs == CS_default) {
00523 cs = default_coordinate_system;
00524 }
00525
00526
00527
00528 bool bMatHasNoShear,bIsLeftHandedMat;
00529
00530 FLOATNAME(LMatrix3) new_mat(mat);
00531
00532 switch (cs) {
00533 case CS_zup_right:
00534 {
00535 unwind_zup_rotation(new_mat, hpr);
00536 bIsLeftHandedMat = false;
00537 }
00538 break;
00539
00540 case CS_yup_right:
00541 {
00542 unwind_yup_rotation(new_mat, hpr);
00543 bIsLeftHandedMat = false;
00544 }
00545 break;
00546
00547 case CS_zup_left:
00548 {
00549 new_mat._m.m._02 = -new_mat._m.m._02;
00550 new_mat._m.m._12 = -new_mat._m.m._12;
00551 new_mat._m.m._20 = -new_mat._m.m._20;
00552 new_mat._m.m._21 = -new_mat._m.m._21;
00553
00554
00555
00556
00557
00558 unwind_zup_rotation(new_mat, hpr);
00559 bIsLeftHandedMat = true;
00560 }
00561 break;
00562
00563 case CS_yup_left:
00564 {
00565 new_mat._m.m._02 = -new_mat._m.m._02;
00566 new_mat._m.m._12 = -new_mat._m.m._12;
00567 new_mat._m.m._20 = -new_mat._m.m._20;
00568 new_mat._m.m._21 = -new_mat._m.m._21;
00569
00570
00571
00572
00573
00574 unwind_yup_rotation(new_mat, hpr);
00575 bIsLeftHandedMat = true;
00576 }
00577 break;
00578
00579 default:
00580 linmath_cat.error()
00581 << "Unexpected coordinate system: " << (int)cs << "\n";
00582 return false;
00583 }
00584
00585 scale[2] = new_mat._m.m._22;
00586 if(bIsLeftHandedMat) {
00587 scale[0] = -new_mat._m.m._00;
00588 scale[1] = -new_mat._m.m._11;
00589 } else {
00590 scale[0] = new_mat._m.m._00;
00591 scale[1] = new_mat._m.m._11;
00592 }
00593
00594 bMatHasNoShear =
00595 (fabs(new_mat(0, 1)) + fabs(new_mat(0, 2)) +
00596 fabs(new_mat(1, 0)) + fabs(new_mat(1, 2)) +
00597 fabs(new_mat(2, 0)) + fabs(new_mat(2, 1))) < 0.0001;
00598
00599 return bMatHasNoShear;
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 bool
00616 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
00617 FLOATNAME(LVecBase3) &scale,
00618 FLOATNAME(LVecBase3) &hpr,
00619 FLOATTYPE roll,
00620 CoordinateSystem cs) {
00621 if (cs == CS_default) {
00622 cs = default_coordinate_system;
00623 }
00624
00625
00626
00627 bool bMatHasNoShear,bIsLeftHandedMat;
00628
00629 FLOATNAME(LMatrix3) new_mat(mat);
00630
00631 switch (cs) {
00632 case CS_zup_right:
00633 {
00634 unwind_zup_rotation(new_mat, hpr, roll);
00635 bIsLeftHandedMat = false;
00636 }
00637 break;
00638
00639 case CS_yup_right:
00640 {
00641 unwind_yup_rotation(new_mat, hpr, roll);
00642 bIsLeftHandedMat = false;
00643 }
00644 break;
00645
00646 case CS_zup_left:
00647 {
00648 new_mat._m.m._02 = -new_mat._m.m._02;
00649 new_mat._m.m._12 = -new_mat._m.m._12;
00650 new_mat._m.m._20 = -new_mat._m.m._20;
00651 new_mat._m.m._21 = -new_mat._m.m._21;
00652
00653
00654
00655
00656
00657 unwind_zup_rotation(new_mat, hpr, roll);
00658 bIsLeftHandedMat = true;
00659 }
00660 break;
00661
00662 case CS_yup_left:
00663 {
00664 new_mat._m.m._02 = -new_mat._m.m._02;
00665 new_mat._m.m._12 = -new_mat._m.m._12;
00666 new_mat._m.m._20 = -new_mat._m.m._20;
00667 new_mat._m.m._21 = -new_mat._m.m._21;
00668
00669
00670
00671
00672
00673 unwind_yup_rotation(new_mat, hpr, roll);
00674 bIsLeftHandedMat = true;
00675 }
00676 break;
00677
00678 default:
00679 linmath_cat.error()
00680 << "Unexpected coordinate system: " << (int)cs << "\n";
00681 return false;
00682 }
00683
00684 scale[2] = new_mat._m.m._22;
00685 if(bIsLeftHandedMat) {
00686 scale[0] = -new_mat._m.m._00;
00687 scale[1] = -new_mat._m.m._11;
00688 } else {
00689 scale[0] = new_mat._m.m._00;
00690 scale[1] = new_mat._m.m._11;
00691 }
00692
00693 bMatHasNoShear =
00694 (fabs(new_mat(0, 1)) + fabs(new_mat(0, 2)) +
00695 fabs(new_mat(1, 0)) + fabs(new_mat(1, 2)) +
00696 fabs(new_mat(2, 0)) + fabs(new_mat(2, 1))) < 0.0001;
00697
00698 return bMatHasNoShear;
00699 }
00700