00001
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
00033
00034 #ifndef GROOVX_GEOM_TXFORM_CC_UTC20050626084023_DEFINED
00035 #define GROOVX_GEOM_TXFORM_CC_UTC20050626084023_DEFINED
00036
00037 #include "txform.h"
00038
00039 #include "geom/rect.h"
00040 #include "geom/vec3.h"
00041
00042 #include "rutz/rand.h"
00043
00044 #include <cmath>
00045 #include <cstring>
00046
00047 #define GVX_NO_PROF
00048 #include "rutz/trace.h"
00049 #include "rutz/debug.h"
00050 GVX_DBG_REGISTER
00051
00052 using geom::vec2d;
00053 using geom::vec3d;
00054
00055 namespace
00056 {
00057 void mul_mtx_4x4(const double* m1, const double* m2, double* result)
00058 {
00059
00060 for (int result_col = 0; result_col < 4; ++result_col)
00061 for (int result_row = 0; result_row < 4; ++result_row)
00062 {
00063 result[result_col * 4 + result_row] =
00064 m1[0 * 4 + result_row] * m2[result_col * 4 + 0]
00065 + m1[1 * 4 + result_row] * m2[result_col * 4 + 1]
00066 + m1[2 * 4 + result_row] * m2[result_col * 4 + 2]
00067 + m1[3 * 4 + result_row] * m2[result_col * 4 + 3];
00068 }
00069 }
00070 }
00071
00072 geom::txform::txform(const vec3d& translation,
00073 const vec3d& scaling,
00074 const vec3d& rotation_axis,
00075 double rotation_angle)
00076 {
00077 GVX_TRACE("geom::txform::txform(tx, scl, rot)");
00078
00079
00080
00081 const double sx = scaling.x();
00082 const double sy = scaling.y();
00083 const double sz = scaling.z();
00084
00085 const double tx = translation.x();
00086 const double ty = translation.y();
00087 const double tz = translation.z();
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 const double rl = rotation_axis.length();
00101
00102 const double rx = rotation_axis.x() / rl;
00103 const double ry = rotation_axis.y() / rl;
00104 const double rz = rotation_axis.z() / rl;
00105
00106 const double c = cos((rotation_angle) * M_PI / 180.0);
00107 const double s = sin((rotation_angle) * M_PI / 180.0);
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 m_mtx[0]=sx*(rx*rx*(1-c)+c); m_mtx[4]=sx*(rx*ry*(1-c)-rz*s); m_mtx[8]=sx*(rx*rz*(1-c)+ry*s); m_mtx[12]=tx;
00124 m_mtx[1]=sy*(ry*rx*(1-c)+rz*s); m_mtx[5]=sy*(ry*ry*(1-c)+c); m_mtx[9]=sy*(ry*rz*(1-c)-rx*s); m_mtx[13]=ty;
00125 m_mtx[2]=sz*(rz*rx*(1-c)-ry*s); m_mtx[6]=sz*(rz*ry*(1-c)+rx*s); m_mtx[10]=sz*(rz*rz*(1-c)+c); m_mtx[14]=tz;
00126 m_mtx[3]=0.0; m_mtx[7]=0.0; m_mtx[11]=0.0; m_mtx[15]=1.0;
00127 }
00128
00129 geom::txform geom::txform::identity()
00130 {
00131 GVX_TRACE("geom::txform::identity");
00132 txform r(true);
00133 r[0] = 1.0; r[4] = 0.0; r[8] = 0.0; r[12] = 0.0;
00134 r[1] = 0.0; r[5] = 1.0; r[9] = 0.0; r[13] = 0.0;
00135 r[2] = 0.0; r[6] = 0.0; r[10] = 1.0; r[14] = 0.0;
00136 r[3] = 0.0; r[7] = 0.0; r[11] = 0.0; r[15] = 1.0;
00137 return r;
00138 }
00139
00140 geom::txform geom::txform::random()
00141 {
00142 GVX_TRACE("geom::txform::random");
00143
00144 static rutz::urand generator(rutz::default_rand_seed);
00145
00146 txform result(true);
00147 for (int i = 0; i < 16; ++i)
00148 result.m_mtx[i] = generator.fdraw_range(0.0, 1.0);
00149 return result;
00150 }
00151
00152 geom::txform geom::txform::orthographic(const geom::rect<double>& b,
00153 double zNear, double zFar)
00154 {
00155 GVX_TRACE("geom::txform::orthographic");
00156
00157 txform result = txform::no_init();
00158
00159 result[0] = 2.0/(b.width());
00160 result[1] = 0;
00161 result[2] = 0;
00162 result[3] = 0;
00163
00164 result[4] = 0;
00165 result[5] = 2.0/(b.height());
00166 result[6] = 0;
00167 result[7] = 0;
00168
00169 result[8] = 0;
00170 result[9] = 0;
00171 result[10] = -2.0/(zFar - zNear);
00172 result[11] = 0;
00173
00174 result[12] = -(b.right()+b.left())/(b.right()-b.left());
00175 result[13] = -(b.top()+b.bottom())/(b.top()-b.bottom());
00176 result[14] = -(zFar+zNear)/(zFar-zNear);
00177 result[15] = 1.0;
00178
00179 return result;
00180 }
00181
00182 geom::txform geom::txform::inverted() const
00183 {
00184 GVX_TRACE("geom::txform::inverted");
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 #define A 10
00201 #define B 11
00202 #define C 12
00203 #define D 13
00204 #define E 14
00205 #define F 15
00206
00207
00208
00209
00210
00211 #define s0 (m_mtx[0])
00212 #define s1 (m_mtx[4])
00213 #define s2 (m_mtx[8])
00214 #define s3 (m_mtx[C])
00215 #define s4 (m_mtx[1])
00216 #define s5 (m_mtx[5])
00217 #define s6 (m_mtx[9])
00218 #define s7 (m_mtx[D])
00219 #define s8 (m_mtx[2])
00220 #define s9 (m_mtx[6])
00221 #define sA (m_mtx[A])
00222 #define sB (m_mtx[E])
00223 #define sC (m_mtx[3])
00224 #define sD (m_mtx[7])
00225 #define sE (m_mtx[B])
00226 #define sF (m_mtx[F])
00227
00228
00229
00230
00231
00232 double cof[16];
00233
00234
00235
00236
00237
00238
00239
00240
00241 {
00242
00243
00244
00245
00246
00247
00248 const double t8D_9C = (s8 * sD) - (s9 * sC);
00249 const double t8E_AC = (s8 * sE) - (sA * sC);
00250 const double t8F_BC = (s8 * sF) - (sB * sC);
00251 const double t9E_AD = (s9 * sE) - (sA * sD);
00252 const double t9F_BD = (s9 * sF) - (sB * sD);
00253 const double tAF_BE = (sA * sF) - (sB * sE);
00254
00255 cof[0]= + tAF_BE*s5 - t9F_BD*s6 + t9E_AD*s7;
00256 cof[1]= - tAF_BE*s4 + t8F_BC*s6 - t8E_AC*s7;
00257 cof[2]= + t9F_BD*s4 - t8F_BC*s5 + t8D_9C*s7;
00258 cof[3]= - t9E_AD*s4 + t8E_AC*s5 - t8D_9C*s6;
00259
00260 cof[4]= - tAF_BE*s1 + t9F_BD*s2 - t9E_AD*s3;
00261 cof[5]= + tAF_BE*s0 - t8F_BC*s2 + t8E_AC*s3;
00262 cof[6]= - t9F_BD*s0 + t8F_BC*s1 - t8D_9C*s3;
00263 cof[7]= + t9E_AD*s0 - t8E_AC*s1 + t8D_9C*s2;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273 {
00274 const double t05_14 = (s0 * s5) - (s1 * s4);
00275 const double t06_24 = (s0 * s6) - (s2 * s4);
00276 const double t07_34 = (s0 * s7) - (s3 * s4);
00277 const double t16_25 = (s1 * s6) - (s2 * s5);
00278 const double t17_35 = (s1 * s7) - (s3 * s5);
00279 const double t27_36 = (s2 * s7) - (s3 * s6);
00280
00281 cof[8]= + t27_36*sD - t17_35*sE + t16_25*sF;
00282 cof[9]= - t27_36*sC + t07_34*sE - t06_24*sF;
00283 cof[A]= + t17_35*sC - t07_34*sD + t05_14*sF;
00284 cof[B]= - t16_25*sC + t06_24*sD - t05_14*sE;
00285
00286 cof[C]= - t27_36*s9 + t17_35*sA - t16_25*sB;
00287 cof[D]= + t27_36*s8 - t07_34*sA + t06_24*sB;
00288 cof[E]= - t17_35*s8 + t07_34*s9 - t05_14*sB;
00289 cof[F]= + t16_25*s8 - t06_24*s9 + t05_14*sA;
00290 }
00291
00292
00293
00294
00295
00296 const double det_reciprocal =
00297 1.0 / (s0*cof[0] +
00298 s1*cof[1] +
00299 s2*cof[2] +
00300 s3*cof[3]);
00301
00302 #undef A
00303 #undef B
00304 #undef C
00305 #undef D
00306 #undef E
00307 #undef F
00308
00309 #undef s0
00310 #undef s1
00311 #undef s2
00312 #undef s3
00313 #undef s4
00314 #undef s5
00315 #undef s6
00316 #undef s7
00317 #undef s8
00318 #undef s9
00319 #undef sA
00320 #undef sB
00321 #undef sC
00322 #undef sD
00323 #undef sE
00324 #undef sF
00325
00326
00327
00328
00329
00330 geom::txform inverse(true);
00331
00332 for (int i = 0; i < 16; ++i)
00333 {
00334 inverse.m_mtx[i] = cof[i] * det_reciprocal;
00335 }
00336
00337 return inverse;
00338 }
00339
00340 void geom::txform::translate(const vec3d& t)
00341 {
00342 GVX_TRACE("geom::txform::translate");
00343
00344 #if 0
00345
00346
00347
00348
00349
00350
00351
00352 txform old_mtx(*this);
00353
00354 double tm[16];
00355 tm[0] = 1.0; tm[4] = 0.0; tm[8] = 0.0; tm[12] = t.x();
00356 tm[1] = 0.0; tm[5] = 1.0; tm[9] = 0.0; tm[13] = t.y();
00357 tm[2] = 0.0; tm[6] = 0.0; tm[10] = 1.0; tm[14] = t.z();
00358 tm[3] = 0.0; tm[7] = 0.0; tm[11] = 0.0; tm[15] = 1.0;
00359
00360 mul_mtx_4x4(old_mtx.m_mtx, tm, this->m_mtx);
00361 #else
00362
00363
00364
00365
00366
00367
00368
00369 m_mtx[12] += t.x()*m_mtx[0] + t.y()*m_mtx[4] + t.z()*m_mtx[8];
00370 m_mtx[13] += t.x()*m_mtx[1] + t.y()*m_mtx[5] + t.z()*m_mtx[9];
00371 m_mtx[14] += t.x()*m_mtx[2] + t.y()*m_mtx[6] + t.z()*m_mtx[10];
00372 m_mtx[15] += t.x()*m_mtx[3] + t.y()*m_mtx[7] + t.z()*m_mtx[11];
00373 #endif
00374 }
00375
00376 void geom::txform::scale(const vec3d& s)
00377 {
00378 GVX_TRACE("geom::txform::scale");
00379
00380 #if 0
00381
00382
00383
00384
00385
00386
00387
00388 txform old_mtx(*this);
00389
00390 double sm[16];
00391 sm[0] = s.x(); sm[4] = 0.0; sm[8] = 0.0; sm[12] = 0.0;
00392 sm[1] = 0.0; sm[5] = s.y(); sm[9] = 0.0; sm[13] = 0.0;
00393 sm[2] = 0.0; sm[6] = 0.0; sm[10] = s.z(); sm[14] = 0.0;
00394 sm[3] = 0.0; sm[7] = 0.0; sm[11] = 0.0; sm[15] = 1.0;
00395
00396 mul_mtx_4x4(old_mtx.m_mtx, sm, this->m_mtx);
00397 #else
00398
00399
00400
00401
00402
00403
00404
00405 m_mtx[0] *= s.x();
00406 m_mtx[1] *= s.x();
00407 m_mtx[2] *= s.x();
00408 m_mtx[3] *= s.x();
00409 m_mtx[4] *= s.y();
00410 m_mtx[5] *= s.y();
00411 m_mtx[6] *= s.y();
00412 m_mtx[7] *= s.y();
00413 m_mtx[8] *= s.z();
00414 m_mtx[9] *= s.z();
00415 m_mtx[10] *= s.z();
00416 m_mtx[11] *= s.z();
00417 #endif
00418 }
00419
00420 void geom::txform::rotate(const vec3d& rotation_axis,
00421 double rotation_angle)
00422 {
00423 GVX_TRACE("geom::txform::rotate");
00424
00425 txform rotation(vec3d(0, 0, 0),
00426 vec3d(1, 1, 1),
00427 rotation_axis, rotation_angle);
00428
00429 this->transform(rotation);
00430 }
00431
00432 geom::txform geom::txform::mtx_mul(const txform& other) const
00433 {
00434 GVX_TRACE("geom::txform::mtx_mul");
00435
00436 txform result(true);
00437
00438 mul_mtx_4x4(this->m_mtx, other.m_mtx, result.m_mtx);
00439
00440 return result;
00441 }
00442
00443 void geom::txform::transform(const geom::txform& other)
00444 {
00445 GVX_TRACE("geom::txform::transform");
00446
00447 txform old_mtx(*this);
00448
00449 mul_mtx_4x4(old_mtx.m_mtx, other.m_mtx, this->m_mtx);
00450 }
00451
00452 vec2d geom::txform::apply_to(const vec2d& input) const
00453 {
00454 GVX_TRACE("geom::txform::apply_to(vec2d)");
00455
00456
00457
00458
00459
00460
00461
00462 const double output_x =
00463 m_mtx[0] * input.x()
00464 + m_mtx[4] * input.y()
00465
00466 + m_mtx[12] * 1.0;
00467
00468 const double output_y =
00469 m_mtx[1] * input.x()
00470 + m_mtx[5] * input.y()
00471
00472 + m_mtx[13] * 1.0;
00473
00474
00475
00476 const double output_w =
00477 m_mtx[3] * input.x()
00478 + m_mtx[7] * input.y()
00479
00480 + m_mtx[15] * 1.0;
00481
00482 return (output_w != 0.0)
00483 ? vec2d(output_x / output_w, output_y / output_w)
00484 : vec2d(0.0, 0.0);
00485 }
00486
00487 vec3d geom::txform::apply_to(const vec3d& input) const
00488 {
00489 GVX_TRACE("geom::txform::apply_to(vec3d)");
00490
00491
00492
00493
00494
00495
00496
00497 const double output_x =
00498 m_mtx[0] * input.x()
00499 + m_mtx[4] * input.y()
00500 + m_mtx[8] * input.z()
00501 + m_mtx[12] * 1.0;
00502
00503 const double output_y =
00504 m_mtx[1] * input.x()
00505 + m_mtx[5] * input.y()
00506 + m_mtx[9] * input.z()
00507 + m_mtx[13] * 1.0;
00508
00509 const double output_z =
00510 m_mtx[2] * input.x()
00511 + m_mtx[6] * input.y()
00512 + m_mtx[10] * input.z()
00513 + m_mtx[14] * 1.0;
00514
00515 const double output_w =
00516 m_mtx[3] * input.x()
00517 + m_mtx[7] * input.y()
00518 + m_mtx[11] * input.z()
00519 + m_mtx[15] * 1.0;
00520
00521 return (output_w != 0.0)
00522 ? vec3d(output_x / output_w,
00523 output_y / output_w,
00524 output_z / output_w)
00525 : vec3d(0.0, 0.0, 0.0);
00526 }
00527
00528 void geom::txform::set_col_major_data(const double* data)
00529 {
00530 GVX_TRACE("geom::txform::set_col_major_data");
00531 for (int i = 0; i < 16; ++i)
00532 m_mtx[i] = data[i];
00533 }
00534
00535 void geom::txform::debug_dump() const
00536 {
00537 GVX_TRACE("geom::txform::debug_dump");
00538 dbg_nl(0);
00539 dbg_print(0, m_mtx[0]); dbg_print(0, m_mtx[4]); dbg_print(0, m_mtx[8]); dbg_print_nl(0, m_mtx[12]);
00540 dbg_print(0, m_mtx[1]); dbg_print(0, m_mtx[5]); dbg_print(0, m_mtx[9]); dbg_print_nl(0, m_mtx[13]);
00541 dbg_print(0, m_mtx[2]); dbg_print(0, m_mtx[6]); dbg_print(0, m_mtx[10]); dbg_print_nl(0, m_mtx[14]);
00542 dbg_print(0, m_mtx[3]); dbg_print(0, m_mtx[7]); dbg_print(0, m_mtx[11]); dbg_print_nl(0, m_mtx[15]);
00543 }
00544
00545 double geom::txform::debug_sse(const txform& ref) const
00546 {
00547 GVX_TRACE("geom::txform::debug_sse");
00548 double result = 0.0;
00549 for (int i = 0; i < 16; ++i)
00550 {
00551 const double diff = this->m_mtx[i] - ref.m_mtx[i];
00552 result += (diff*diff);
00553 }
00554 return result;
00555 }
00556
00557 static const char __attribute__((used)) vcid_groovx_geom_txform_cc_utc20050626084023[] = "$Id: txform.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00558 #endif // !GROOVX_GEOM_TXFORM_CC_UTC20050626084023_DEFINED