1/*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: math_Matrix44.ipp 4 5 Copyright (C)2009-2010 Nintendo Co., Ltd. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Revision: 13623 $ 14 *---------------------------------------------------------------------------*/ 15 16#include <cmath> 17#include <nn/math/math_Vector3.h> 18 19namespace nn { 20namespace math { 21namespace ARMv6 { 22/*! 23 @name ユーティリティ 24 @{ 25*/ 26 27/*!--------------------------------------------------------------------------* 28 @brief ベクトルを行列で変換します。ベクトルの 4 要素目を 1 として計算します。 29 30 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pV と同じベクトルを指していても構いません。 31 @param[in] pM 変換行列へのポインタ。 32 @param[in] pV 元となるベクトルへのポインタ。 33 34 @return pOut を返します。 35 *---------------------------------------------------------------------------*/ 36NN_MATH_INLINE VEC4* 37VEC3TransformC(VEC4* pOut, const MTX44* pM, const VEC3* pV) 38{ 39 VEC4 tmp; 40 tmp.x = pM->f._00 * pV->x + pM->f._01 * pV->y + pM->f._02 * pV->z + pM->f._03; 41 tmp.y = pM->f._10 * pV->x + pM->f._11 * pV->y + pM->f._12 * pV->z + pM->f._13; 42 tmp.z = pM->f._20 * pV->x + pM->f._21 * pV->y + pM->f._22 * pV->z + pM->f._23; 43 tmp.w = pM->f._30 * pV->x + pM->f._31 * pV->y + pM->f._32 * pV->z + pM->f._33; 44 45 pOut->x = tmp.x; 46 pOut->y = tmp.y; 47 pOut->z = tmp.z; 48 pOut->w = tmp.w; 49 50 return pOut; 51} 52 53/*! 54 @} 55*/ 56 57/* ------------------------------------------------------------------------ 58 MTX44 59 ------------------------------------------------------------------------ */ 60 61/*! 62 @name 行列 63 @{ 64*/ 65 66 67 68/*!--------------------------------------------------------------------------* 69 @brief 行列をコピーします。 70 71 @param[out] pOut コピー先の行列へのポインタ。 72 @param[in] p コピー元の行列へのポインタ 73 74 @return pOut を返します。 75 *---------------------------------------------------------------------------*/ 76NN_MATH_INLINE MTX44* 77MTX44CopyC(MTX44* pOut, const MTX44* p) 78{ 79 if (pOut != p) 80 { 81 *pOut = *p; 82 } 83 84 return pOut; 85} 86 87/*!--------------------------------------------------------------------------* 88 @brief 行列の和を計算します。 89 90 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。 91 @param[in] p1 左辺値へのポインタ。 92 @param[in] p2 右辺値へのポインタ。 93 94 @return pOut を返します。 95 *---------------------------------------------------------------------------*/ 96NN_MATH_INLINE MTX44* 97MTX44AddC(MTX44* pOut, const MTX44* p1, const MTX44* p2) 98{ 99 pOut->f._00 = p1->f._00 + p2->f._00; 100 pOut->f._01 = p1->f._01 + p2->f._01; 101 pOut->f._02 = p1->f._02 + p2->f._02; 102 pOut->f._03 = p1->f._03 + p2->f._03; 103 104 pOut->f._10 = p1->f._10 + p2->f._10; 105 pOut->f._11 = p1->f._11 + p2->f._11; 106 pOut->f._12 = p1->f._12 + p2->f._12; 107 pOut->f._13 = p1->f._13 + p2->f._13; 108 109 pOut->f._20 = p1->f._20 + p2->f._20; 110 pOut->f._21 = p1->f._21 + p2->f._21; 111 pOut->f._22 = p1->f._22 + p2->f._22; 112 pOut->f._23 = p1->f._23 + p2->f._23; 113 114 pOut->f._30 = p1->f._30 + p2->f._30; 115 pOut->f._31 = p1->f._31 + p2->f._31; 116 pOut->f._32 = p1->f._32 + p2->f._32; 117 pOut->f._33 = p1->f._33 + p2->f._33; 118 119 return pOut; 120} 121 122 123 124/*!--------------------------------------------------------------------------* 125 @brief 行列のスカラー積を計算します。 126 127 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じ行列を指していても構いません。 128 @param[in] p 元の行列のポインタ。 129 @param[in] f 掛ける数 130 131 @return pOut を返します。 132 *---------------------------------------------------------------------------*/ 133NN_MATH_INLINE MTX44* 134MTX44MultC(MTX44* pOut, const MTX44* p, f32 f) 135{ 136 pOut->f._00 = p->f._00 * f; 137 pOut->f._01 = p->f._01 * f; 138 pOut->f._02 = p->f._02 * f; 139 pOut->f._03 = p->f._03 * f; 140 141 pOut->f._10 = p->f._10 * f; 142 pOut->f._11 = p->f._11 * f; 143 pOut->f._12 = p->f._12 * f; 144 pOut->f._13 = p->f._13 * f; 145 146 pOut->f._20 = p->f._20 * f; 147 pOut->f._21 = p->f._21 * f; 148 pOut->f._22 = p->f._22 * f; 149 pOut->f._23 = p->f._23 * f; 150 151 pOut->f._30 = p->f._30 * f; 152 pOut->f._31 = p->f._31 * f; 153 pOut->f._32 = p->f._32 * f; 154 pOut->f._33 = p->f._33 * f; 155 156 return pOut; 157} 158 159 160/*!--------------------------------------------------------------------------* 161 @brief 行列の転置を取得します。 162 163 @param[in] pOut 計算結果を受け取るバッファへのポインタ。pSrcと同じ行列を指していても構いません。 164 @param[in] pSrc 元となる行列へのポインタ。 165 166 @return pOut を返します。 167 *---------------------------------------------------------------------------*/ 168NN_MATH_INLINE MTX44* 169MTX44TransposeC(MTX44* pOut, const MTX44 *pSrc) 170{ 171 MTX44 tmp; 172 const MTX44 *pMtx; 173 174 if (pOut != pSrc) 175 { 176 pMtx = pSrc; 177 pOut->f._00 = pSrc->f._00; 178 pOut->f._11 = pSrc->f._11; 179 pOut->f._22 = pSrc->f._22; 180 pOut->f._33 = pSrc->f._33; 181 } 182 else 183 { 184 pMtx = &tmp; 185 tmp.f._01 = pSrc->f._01; 186 tmp.f._02 = pSrc->f._02; 187 tmp.f._03 = pSrc->f._03; 188 tmp.f._12 = pSrc->f._12; 189 tmp.f._13 = pSrc->f._13; 190 tmp.f._23 = pSrc->f._23; 191 } 192 193 pOut->f._01 = pSrc->f._10; 194 pOut->f._02 = pSrc->f._20; 195 pOut->f._03 = pSrc->f._30; 196 pOut->f._12 = pSrc->f._21; 197 pOut->f._13 = pSrc->f._31; 198 pOut->f._23 = pSrc->f._32; 199 200 pOut->f._10 = pMtx->f._01; 201 pOut->f._20 = pMtx->f._02; 202 pOut->f._30 = pMtx->f._03; 203 pOut->f._21 = pMtx->f._12; 204 pOut->f._31 = pMtx->f._13; 205 pOut->f._32 = pMtx->f._23; 206 207 return pOut; 208} 209 210 211/*!--------------------------------------------------------------------------* 212 @brief 射影行列を視野角とアスペクト比から作成します。 213 214 @param[out] pOut 射影行列を格納する行列へのポインタ。 215 @param[in] fovy 縦方向の視野角(Radian) 216 @param[in] aspect 視野のアスペクト比(幅/高さ) 217 @param[in] n ニアクリッピング面までの距離。 218 @param[in] f ファークリッピング面までの距離。 219 220 @return pOut を返します。 221 *---------------------------------------------------------------------------*/ 222NN_MATH_INLINE MTX44* 223MTX44PerspectiveRadC(MTX44* pOut, f32 fovy, f32 aspect, f32 n, f32 f) 224{ 225 NN_NULL_ASSERT(pOut); 226 227 f32 (*const m)[4] = pOut->m; 228 229 // find the cotangent of half the (YZ) field of view 230 231 const f32 angle = fovy * 0.5f; 232 233 const f32 cot = 1.0f / ::std::tanf(angle); 234 235 m[0][0] = cot / aspect; 236 m[0][1] = 0.0f; 237 m[0][2] = 0.0f; 238 m[0][3] = 0.0f; 239 240 m[1][0] = 0.0f; 241 m[1][1] = cot; 242 m[1][2] = 0.0f; 243 m[1][3] = 0.0f; 244 245 m[2][0] = 0.0f; 246 m[2][1] = 0.0f; 247 248 const f32 tmp = 1.0f / (f - n); 249 m[2][2] = f * tmp; 250 m[2][3] = f * n * tmp; 251 252 m[3][0] = 0.0f; 253 m[3][1] = 0.0f; 254 m[3][2] = -1.0f; 255 m[3][3] = 0.0f; 256 257 return pOut; 258} 259NN_MATH_INLINE MTX44* 260MTX44PerspectiveRadC_FAST(MTX44* pOut, f32 fovy, f32 aspect, f32 n, f32 f) 261{ 262 NN_NULL_ASSERT(pOut); 263 264 f32 (*const m)[4] = pOut->m; 265 266 // find the cotangent of half the (YZ) field of view 267 268 const f32 angle = fovy * 0.5f; 269#if (MTX44PERSPECTIVERAD_CONFIG == D_FAST_C_ALGO) 270 f32 sin, cos; 271 SinCosFIdx(&sin, &cos, NN_MATH_RAD_TO_FIDX(angle)); 272 const f32 cot = cos/sin; 273#else 274 const f32 cot = 1.0f / ::std::tanf(angle); 275#endif 276 const f32 tmp = 1.0f / (f - n); 277 278 register f32 m00, m11, m22, m23; 279 280 m00 = cot / aspect; 281 m11 = cot; 282 m22 = f * tmp; 283 m23 = f * n * tmp; 284 285 m[0][1] = 0.0f; 286 m[0][2] = 0.0f; 287 m[0][3] = 0.0f; 288 m[1][0] = 0.0f; 289 m[1][2] = 0.0f; 290 m[1][3] = 0.0f; 291 m[2][0] = 0.0f; 292 m[2][1] = 0.0f; 293 m[3][0] = 0.0f; 294 m[3][1] = 0.0f; 295 m[3][2] = -1.0f; 296 m[3][3] = 0.0f; 297 298 m[0][0] = m00; 299 m[1][1] = m11; 300 m[2][2] = m22; 301 m[2][3] = m23; 302 303 304 return pOut; 305} 306 307/*!--------------------------------------------------------------------------* 308 @brief 射影行列をニアクリッピング面での視錐台を元に作成します。 309 引数の順序が OpenGL 準拠になっているので注意。 310 311 @param[out] pOut 射影行列を格納する行列へのポインタ。 312 @param[in] l ニアクリッピング面での視錐台左辺の X 座標 313 @param[in] r ニアクリッピング面での視錐台右辺の X 座標 314 @param[in] b ニアクリッピング面での視錐台下辺の Y 座標 315 @param[in] t ニアクリッピング面での視錐台上辺の Y 座標 316 @param[in] n ニアクリッピング面までの距離。 317 @param[in] f ファークリッピング面までの距離。 318 319 @return pOut を返します。 320 *---------------------------------------------------------------------------*/ 321NN_MATH_INLINE MTX44* 322MTX44FrustumC(MTX44* pOut, f32 l, f32 r, f32 b, f32 t, f32 n, f32 f) 323{ 324 NN_NULL_ASSERT( pOut ); 325 326 // NOTE: Be careful about "l" vs. "1" below!!! 327 328 f32 (*const m)[4] = pOut->m; 329 f32 tmp = 1.0f / (r - l); 330 m[0][0] = (2*n) * tmp; 331 m[0][1] = 0.0f; 332 m[0][2] = (r + l) * tmp; 333 m[0][3] = 0.0f; 334 335 tmp = 1.0f / (t - b); 336 m[1][0] = 0.0f; 337 m[1][1] = (2*n) * tmp; 338 m[1][2] = (t + b) * tmp; 339 m[1][3] = 0.0f; 340 341 m[2][0] = 0.0f; 342 m[2][1] = 0.0f; 343 344 tmp = 1.0f / (f - n); 345 346 m[2][2] = f * tmp; 347 m[2][3] = f * n * tmp; 348 349 m[3][0] = 0.0f; 350 m[3][1] = 0.0f; 351 m[3][2] = -1.0f; 352 m[3][3] = 0.0f; 353 354 return pOut; 355} 356NN_MATH_INLINE MTX44* 357MTX44FrustumC_FAST(MTX44* pOut, f32 l, f32 r, f32 b, f32 t, f32 n, f32 f) 358{ 359 NN_NULL_ASSERT( pOut ); 360 361 // NOTE: Be careful about "l" vs. "1" below!!! 362 363 f32 (*const m)[4] = pOut->m; 364 f32 tmp1 = 1.0f / (r - l); 365 f32 tmp3 = 1.0f / (f - n); 366 f32 tmp2 = 1.0f / (t - b); 367 368 register f32 m00, m02, m11, m12, m22, m23; 369 370 m00 = (2*n) * tmp1; 371 m02 = (r + l) * tmp1; 372 373 m11 = (2*n) * tmp2; 374 m12 = (t + b) * tmp2; 375 376 m22 = f * tmp3; 377 m23 = f * n * tmp3; 378 379 m[0][1] = 0.0f; 380 m[0][3] = 0.0f; 381 382 m[1][0] = 0.0f; 383 m[1][3] = 0.0f; 384 385 m[2][0] = 0.0f; 386 m[2][1] = 0.0f; 387 388 m[3][0] = 0.0f; 389 m[3][1] = 0.0f; 390 m[3][2] = -1.0f; 391 m[3][3] = 0.0f; 392 393 m[0][0] = m00; 394 m[0][2] = m02; 395 396 m[1][1] = m11; 397 m[1][2] = m12; 398 399 m[2][2] = m22; 400 m[2][3] = m23; 401 402 return pOut; 403} 404 405 406/*!--------------------------------------------------------------------------* 407 @brief 正射影行列を作成します。 408 引数の順序が OpenGL 準拠になっているので注意。 409 410 @param[out] pOut 射影行列を格納する行列へのポインタ。 411 @param[in] l ニアクリッピング面での視錐台左辺の X 座標 412 @param[in] r ニアクリッピング面での視錐台右辺の X 座標 413 @param[in] b ニアクリッピング面での視錐台下辺の Y 座標 414 @param[in] t ニアクリッピング面での視錐台上辺の Y 座標 415 @param[in] n ニアクリッピング面までの距離。 416 @param[in] f ファークリッピング面までの距離。 417 418 @return pOut を返します。 419 *---------------------------------------------------------------------------*/ 420NN_MATH_INLINE MTX44* 421MTX44OrthoC(MTX44* pOut, f32 l, f32 r, f32 b, f32 t, f32 n, f32 f) 422{ 423 NN_NULL_ASSERT( pOut ); 424 425 // NOTE: Be careful about "l" vs. "1" below!!! 426 427 f32 (*const m)[4] = pOut->m; 428 f32 tmp = 1.0f / (r - l); 429 m[0][0] = 2.0f * tmp; 430 m[0][1] = 0.0f; 431 m[0][2] = 0.0f; 432 m[0][3] = -(r + l) * tmp; 433 434 tmp = 1.0f / (t - b); 435 m[1][0] = 0.0f; 436 m[1][1] = 2.0f * tmp; 437 m[1][2] = 0.0f; 438 m[1][3] = -(t + b) * tmp; 439 440 m[2][0] = 0.0f; 441 m[2][1] = 0.0f; 442 443 tmp = 1.0f / (f - n); 444 445 m[2][2] = tmp; 446 m[2][3] = n * tmp; 447 448 m[3][0] = 0.0f; 449 m[3][1] = 0.0f; 450 m[3][2] = 0.0f; 451 m[3][3] = 1.0f; 452 453 return pOut; 454} 455NN_MATH_INLINE MTX44* 456MTX44OrthoC_FAST(MTX44* pOut, f32 l, f32 r, f32 b, f32 t, f32 n, f32 f) 457{ 458 NN_NULL_ASSERT( pOut ); 459 460 // NOTE: Be careful about "l" vs. "1" below!!! 461 462 f32 (*const m)[4] = pOut->m; 463 register f32 tmp1 = 1.0f / (r - l); 464 register f32 tmp2 = 1.0f / (t - b); 465 register f32 tmp3 = 1.0f / (f - n); 466 register f32 m00, m03, m11, m13, m22, m23; 467 468 m00 = 2.0f * tmp1; 469 m03 = -(r + l) * tmp1; 470 471 m11 = 2.0f * tmp2; 472 m13 = -(t + b) * tmp2; 473 474 m22 = tmp3; 475 m23 = n * tmp3; 476 477 m[0][1] = 0.0f; 478 m[0][2] = 0.0f; 479 480 m[1][0] = 0.0f; 481 m[1][2] = 0.0f; 482 483 m[2][0] = 0.0f; 484 m[2][1] = 0.0f; 485 486 m[3][0] = 0.0f; 487 m[3][1] = 0.0f; 488 m[3][2] = 0.0f; 489 m[3][3] = 1.0f; 490 491 m[0][0] = m00; 492 m[0][3] = m03; 493 m[1][1] = m11; 494 m[1][3] = m13; 495 m[2][2] = m22; 496 m[2][3] = m23; 497 498 return pOut; 499} 500 501 502 /*---------------------------------------------------------------------------* 503 Description: 画面方向に向けて射影行列を回転します。 504 505 Arguments: pOut 回転をおこなう行列へのポインタ 506 pivot 507 508 Returns: 509 *---------------------------------------------------------------------------*/ 510 inline MTX44* 511 MTX44PivotC( MTX44* pOut, PivotDirection pivot ) 512 { 513 // TODO: 処理の最適化が必要。 514 515 const f32 PIVOT_ROTATION_SIN_COS[ PIVOT_NUM ][ 2 ] = 516 { 517 #ifdef NN_PLATFORM_CTR 518 { 0.0f, 1.0f }, // NONE 519 { -1.0f, 0.0f }, // TO_UP 520 { 0.0f, -1.0f }, // TO_RIGHT 521 { 1.0f, 0.0f }, // TO_BOTTOM 522 { 0.0f, 1.0f }, // TO_LEFT 523 #else 524 { 0.0f, 1.0f }, // NONE 525 { 0.0f, 1.0f }, // TO_UP 526 { -1.0f, 0.0f }, // TO_RIGHT 527 { 0.0f, -1.0f }, // TO_BOTTOM 528 { 1.0f, 0.0f }, // TO_LEFT 529 #endif 530 }; 531 532 if ( pivot == PIVOT_NONE ) 533 { 534 return pOut; 535 } 536 537 f32 sin = PIVOT_ROTATION_SIN_COS[ pivot ][ 0 ]; 538 f32 cos = PIVOT_ROTATION_SIN_COS[ pivot ][ 1 ]; 539 540 f32 (*const m)[4] = pOut->m; 541 542 if ( sin == 0.0f ) 543 { 544 m[0][0] = cos * m[0][0]; 545 m[0][1] = cos * m[0][1]; 546 m[0][2] = cos * m[0][2]; 547 m[0][3] = cos * m[0][3]; 548 549 m[1][0] = cos * m[1][0]; 550 m[1][1] = cos * m[1][1]; 551 m[1][2] = cos * m[1][2]; 552 m[1][3] = cos * m[1][3]; 553 } 554 else // if ( cos == 0.0f ) 555 { 556 f32 tmp = m[0][0]; 557 m[0][0] = -sin * m[1][0]; 558 m[1][0] = sin * tmp; 559 560 tmp = m[0][1]; 561 m[0][1] = -sin * m[1][1]; 562 m[1][1] = sin * tmp; 563 564 tmp = m[0][2]; 565 m[0][2] = -sin * m[1][2]; 566 m[1][2] = sin * tmp; 567 568 tmp = m[0][3]; 569 m[0][3] = -sin * m[1][3]; 570 m[1][3] = sin * tmp; 571 } 572 573 return pOut; 574 575 } 576 inline MTX44* 577 MTX44PivotC_FAST( MTX44* pOut, PivotDirection pivot ) 578 { 579 f32 (*const m)[4] = pOut->m; 580 #ifdef NN_PLATFORM_CTR 581 if ( ( pivot == PIVOT_NONE ) || ( pivot == PIVOT_UPSIDE_TO_LEFT ) ) 582 #else 583 if ( ( pivot == PIVOT_NONE ) || ( pivot == PIVOT_UPSIDE_TO_TOP ) ) 584 #endif 585 { 586 return pOut; 587 } 588 589 #ifdef NN_PLATFORM_CTR 590 if ( pivot == PIVOT_UPSIDE_TO_RIGHT ) 591 #else 592 if ( pivot == PIVOT_UPSIDE_TO_BOTTOM ) 593 #endif 594 { 595 register f32 m00, m01, m02, m03, m10, m11, m12, m13; 596 597 m00 = -m[0][0]; 598 m01 = -m[0][1]; 599 m02 = -m[0][2]; 600 m03 = -m[0][3]; 601 602 m10 = -m[1][0]; 603 m11 = -m[1][1]; 604 m12 = -m[1][2]; 605 m13 = -m[1][3]; 606 607 m[0][0] = m00; 608 m[0][1] = m01; 609 m[0][2] = m02; 610 m[0][3] = m03; 611 612 m[1][0] = m10; 613 m[1][1] = m11; 614 m[1][2] = m12; 615 m[1][3] = m13; 616 } 617 #ifdef NN_PLATFORM_CTR 618 else if ( pivot == PIVOT_UPSIDE_TO_BOTTOM ) 619 #else 620 else if ( pivot == PIVOT_UPSIDE_TO_LEFT ) 621 #endif 622 { 623 register f32 m00, m01, m02, m03, m10, m11, m12, m13; 624 625 m10 = m[0][0]; 626 m11 = m[0][1]; 627 m12 = m[0][2]; 628 m13 = m[0][3]; 629 630 m00 = -m[1][0]; 631 m01 = -m[1][1]; 632 m02 = -m[1][2]; 633 m03 = -m[1][3]; 634 635 m[0][0] = m00; 636 m[0][1] = m01; 637 m[0][2] = m02; 638 m[0][3] = m03; 639 640 m[1][0] = m10; 641 m[1][1] = m11; 642 m[1][2] = m12; 643 m[1][3] = m13; 644 } 645 #ifdef NN_PLATFORM_CTR 646 else // if ( pivot == PIVOT_UPSIDE_TO_TOP ) 647 #else 648 else // if ( pivot == PIVOT_UPSIDE_TO_RIGHT ) 649 #endif 650 { 651 register f32 m00, m01, m02, m03, m10, m11, m12, m13; 652 653 m10 = -m[0][0]; 654 m11 = -m[0][1]; 655 m12 = -m[0][2]; 656 m13 = -m[0][3]; 657 658 m00 = m[1][0]; 659 m01 = m[1][1]; 660 m02 = m[1][2]; 661 m03 = m[1][3]; 662 663 m[0][0] = m00; 664 m[0][1] = m01; 665 m[0][2] = m02; 666 m[0][3] = m03; 667 668 m[1][0] = m10; 669 m[1][1] = m11; 670 m[1][2] = m12; 671 m[1][3] = m13; 672 } 673 return pOut; 674 } 675 676 677/*!--------------------------------------------------------------------------* 678 @brief 行列の積を計算します。 679 680 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。 681 @param[in] p1 左辺値へのポインタ。 682 @param[in] p2 右辺値へのポインタ。 683 684 @return pOut を返します。 685 *---------------------------------------------------------------------------*/ 686NN_MATH_INLINE MTX44* 687MTX44MultC(MTX44* pOut, const MTX44* __restrict p1, const MTX44* __restrict p2) 688{ 689 NN_NULL_ASSERT( pOut ); 690 NN_NULL_ASSERT( p1 ); 691 NN_NULL_ASSERT( p2 ); 692 693 MTX44 mTmp; 694 695 MTX44* __restrict pDst = ( pOut == p1 || pOut == p2 ) ? &mTmp : pOut; 696 697 pDst->f._00 = p1->f._00 * p2->f._00 + p1->f._01 * p2->f._10 + p1->f._02 * p2->f._20 + p1->f._03 * p2->f._30; 698 pDst->f._01 = p1->f._00 * p2->f._01 + p1->f._01 * p2->f._11 + p1->f._02 * p2->f._21 + p1->f._03 * p2->f._31; 699 pDst->f._02 = p1->f._00 * p2->f._02 + p1->f._01 * p2->f._12 + p1->f._02 * p2->f._22 + p1->f._03 * p2->f._32; 700 pDst->f._03 = p1->f._00 * p2->f._03 + p1->f._01 * p2->f._13 + p1->f._02 * p2->f._23 + p1->f._03 * p2->f._33; 701 702 pDst->f._10 = p1->f._10 * p2->f._00 + p1->f._11 * p2->f._10 + p1->f._12 * p2->f._20 + p1->f._13 * p2->f._30; 703 pDst->f._11 = p1->f._10 * p2->f._01 + p1->f._11 * p2->f._11 + p1->f._12 * p2->f._21 + p1->f._13 * p2->f._31; 704 pDst->f._12 = p1->f._10 * p2->f._02 + p1->f._11 * p2->f._12 + p1->f._12 * p2->f._22 + p1->f._13 * p2->f._32; 705 pDst->f._13 = p1->f._10 * p2->f._03 + p1->f._11 * p2->f._13 + p1->f._12 * p2->f._23 + p1->f._13 * p2->f._33; 706 707 pDst->f._20 = p1->f._20 * p2->f._00 + p1->f._21 * p2->f._10 + p1->f._22 * p2->f._20 + p1->f._23 * p2->f._30; 708 pDst->f._21 = p1->f._20 * p2->f._01 + p1->f._21 * p2->f._11 + p1->f._22 * p2->f._21 + p1->f._23 * p2->f._31; 709 pDst->f._22 = p1->f._20 * p2->f._02 + p1->f._21 * p2->f._12 + p1->f._22 * p2->f._22 + p1->f._23 * p2->f._32; 710 pDst->f._23 = p1->f._20 * p2->f._03 + p1->f._21 * p2->f._13 + p1->f._22 * p2->f._23 + p1->f._23 * p2->f._33; 711 712 pDst->f._30 = p1->f._30 * p2->f._00 + p1->f._31 * p2->f._10 + p1->f._32 * p2->f._20 + p1->f._33 * p2->f._30; 713 pDst->f._31 = p1->f._30 * p2->f._01 + p1->f._31 * p2->f._11 + p1->f._32 * p2->f._21 + p1->f._33 * p2->f._31; 714 pDst->f._32 = p1->f._30 * p2->f._02 + p1->f._31 * p2->f._12 + p1->f._32 * p2->f._22 + p1->f._33 * p2->f._32; 715 pDst->f._33 = p1->f._30 * p2->f._03 + p1->f._31 * p2->f._13 + p1->f._32 * p2->f._23 + p1->f._33 * p2->f._33; 716 717 if ( pDst != pOut ) 718 { 719 MTX44Copy( pOut, pDst ); 720 } 721 722 return pOut; 723} 724 725namespace { 726 inline void SwapF(f32 &a, f32 &b) 727 { 728 f32 tmp; 729 tmp = a; 730 a = b; 731 b = tmp; 732 } 733} // namespace (unnamed) 734 735 736/*!--------------------------------------------------------------------------* 737 @brief 行列の逆行列を計算します。 738 739 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じ行列を指していても構いません。 740 @param[in] p 元となる行列へのポインタ。 741 742 @return 逆行列が存在すれば 1 を、存在しなければ 0 を返します。 743 *---------------------------------------------------------------------------*/ 744NN_MATH_INLINE u32 745MTX44InverseC(MTX44* pOut, const MTX44* p) 746{ 747 MTX44 mTmp; 748 f32 (*src)[4]; 749 f32 (*inv)[4]; 750 f32 w; 751 752 NN_NULL_ASSERT( p ); 753 NN_NULL_ASSERT( pOut ); 754 755 MTX44Copy(&mTmp, p); 756 MTX44Identity(pOut); 757 758 src = mTmp.m; 759 inv = pOut->m; 760 761 for (int i = 0; i < 4; ++i) 762 { 763 f32 max = 0.0f; 764 s32 swp = i; 765 766 // ---- partial pivoting ----- 767 for(int k = i ; k < 4 ; k++ ) 768 { 769 f32 ftmp; 770 ftmp = ::std::fabs(src[k][i]); 771 if ( ftmp > max ) 772 { 773 max = ftmp; 774 swp = k; 775 } 776 } 777 778 // check singular matrix 779 //(or can't solve inverse matrix with this algorithm) 780 if ( max == 0.0f ) 781 { 782 return 0; 783 } 784 785 // swap row 786 if ( swp != i ) 787 { 788 for (int k = 0; k < 4; k++) 789 { 790 SwapF(src[i][k], src[swp][k]); 791 SwapF(inv[i][k], inv[swp][k]); 792 } 793 } 794 795 // ---- pivoting end ---- 796 797 w = 1.0f / src[i][i]; 798 for (int j = 0; j < 4; ++j) 799 { 800 src[i][j] *= w; 801 inv[i][j] *= w; 802 } 803 804 for (int k = 0; k < 4; ++k ) 805 { 806 if ( k == i ) 807 continue; 808 809 w = src[k][i]; 810 for (int j = 0; j < 4; ++j) 811 { 812 src[k][j] -= src[i][j] * w; 813 inv[k][j] -= inv[i][j] * w; 814 } 815 } 816 } 817 818 return 1; 819} 820NN_MATH_INLINE u32 821MTX44InverseC_FAST_ALGO(MTX44* pOut, const MTX44* p) 822{ 823 const f32 (*src)[4]; 824 f32 (*inv)[4]; 825 826 NN_NULL_ASSERT( p ); 827 NN_NULL_ASSERT( pOut ); 828 829 src = p->m; 830 inv = pOut->m; 831 832 f32 a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44; 833 f32 b11, b12, b13, b14, b21, b22, b23, b24, b31, b32, b33, b34, b41, b42, b43, b44; 834 f32 det; 835 836 a11 = src[0][0]; 837 a12 = src[0][1]; 838 a13 = src[0][2]; 839 a14 = src[0][3]; 840 841 a21 = src[1][0]; 842 a22 = src[1][1]; 843 a23 = src[1][2]; 844 a24 = src[1][3]; 845 846 a31 = src[2][0]; 847 a32 = src[2][1]; 848 a33 = src[2][2]; 849 a34 = src[2][3]; 850 851 a41 = src[3][0]; 852 a42 = src[3][1]; 853 a43 = src[3][2]; 854 a44 = src[3][3]; 855 856 det = a11*(a22*a33*a44 + a23*a34*a42 + a24*a32*a43) 857 + a12*(a21*a34*a43 + a23*a31*a44 + a24*a33*a41) 858 + a13*(a21*a32*a44 + a22*a34*a41 + a24*a31*a42) 859 + a14*(a21*a33*a42 + a22*a31*a43 + a23*a32*a41) 860 - a11*(a22*a34*a43 + a23*a32*a44 + a24*a33*a42) 861 - a12*(a21*a33*a44 + a23*a34*a41 + a24*a31*a43) 862 - a13*(a21*a34*a42 + a22*a31*a44 + a24*a32*a41) 863 - a14*(a21*a32*a43 + a22*a33*a41 + a23*a31*a42); 864 865 if(det==0.0f) 866 return 0; 867 868 det = 1.0f / det; 869 870 f32 a33xa44_a34xa43, a32xa44_a34xa42, a33xa42_a32xa43, 871 a33xa41_a31xa43, a31xa44_a34xa41, a32xa41_a31xa42; 872 873 a33xa44_a34xa43 = a33*a44 - a34*a43; 874 a32xa44_a34xa42 = a32*a44 - a34*a42; 875 a33xa42_a32xa43 = a33*a42 - a32*a43; 876 a33xa41_a31xa43 = a33*a41 - a31*a43; 877 a31xa44_a34xa41 = a31*a44 - a34*a41; 878 a32xa41_a31xa42 = a32*a41 - a31*a42; 879 880 f32 a23xa44_a24xa43, a24xa33_a23xa34, a24xa42_a22xa44, a22xa43_a23xa42, 881 a22xa34_a24xa32, a23xa32_a22xa33, a21xa44_a24xa41, a23xa41_a21xa43, 882 a24xa31_a21xa34, a21xa33_a23xa31, a21xa42_a22xa41, a22xa31_a21xa32; 883 884 a23xa44_a24xa43 = a23*a44 - a24*a43; 885 a24xa33_a23xa34 = a24*a33 - a23*a34; 886 a24xa42_a22xa44 = a24*a42 - a22*a44; 887 a22xa43_a23xa42 = a22*a43 - a23*a42; 888 a22xa34_a24xa32 = a22*a34 - a24*a32; 889 a23xa32_a22xa33 = a23*a32 - a22*a33; 890 a21xa44_a24xa41 = a21*a44 - a24*a41; 891 a23xa41_a21xa43 = a23*a41 - a21*a43; 892 a24xa31_a21xa34 = a24*a31 - a21*a34; 893 a21xa33_a23xa31 = a21*a33 - a23*a31; 894 a21xa42_a22xa41 = a21*a42 - a22*a41; 895 a22xa31_a21xa32 = a22*a31 - a21*a32; 896 897 b11 =( a22*a33xa44_a34xa43) - (a23*a32xa44_a34xa42) - (a24*a33xa42_a32xa43); 898 b12 =( a13*a32xa44_a34xa42) + (a14*a33xa42_a32xa43) - (a12*a33xa44_a34xa43); 899 b13 =( a12*a23xa44_a24xa43) + (a13*a24xa42_a22xa44) + (a14*a22xa43_a23xa42); 900 b14 =( a12*a24xa33_a23xa34) + (a13*a22xa34_a24xa32) + (a14*a23xa32_a22xa33); 901 b21 =( a23*a31xa44_a34xa41) + (a24*a33xa41_a31xa43) - (a21*a33xa44_a34xa43); 902 b22 =( a11*a33xa44_a34xa43) - (a13*a31xa44_a34xa41) - (a14*a33xa41_a31xa43); 903 b23 =( a13*a21xa44_a24xa41) + (a14*a23xa41_a21xa43) - (a11*a23xa44_a24xa43); 904 b24 =( a13*a24xa31_a21xa34) + (a14*a21xa33_a23xa31) - (a11*a24xa33_a23xa34); 905 b31 =( a21*a32xa44_a34xa42) - (a22*a31xa44_a34xa41) - (a24*a32xa41_a31xa42); 906 b32 =( a12*a31xa44_a34xa41) + (a14*a32xa41_a31xa42) - (a11*a32xa44_a34xa42); 907 b33 =( a14*a21xa42_a22xa41) - (a11*a24xa42_a22xa44) - (a12*a21xa44_a24xa41); 908 b34 =( a14*a22xa31_a21xa32) - (a11*a22xa34_a24xa32) - (a12*a24xa31_a21xa34); 909 b41 =( a21*a33xa42_a32xa43) - (a22*a33xa41_a31xa43) + (a23*a32xa41_a31xa42); 910 b42 =( a12*a33xa41_a31xa43) - (a13*a32xa41_a31xa42) - (a11*a33xa42_a32xa43); 911 b43 =(-a13*a21xa42_a22xa41) - (a11*a22xa43_a23xa42) - (a12*a23xa41_a21xa43); 912 b44 =(-a13*a22xa31_a21xa32) - (a11*a23xa32_a22xa33) - (a12*a21xa33_a23xa31); 913 914 b11 = b11 * det; 915 b12 = b12 * det; 916 b13 = b13 * det; 917 b14 = b14 * det; 918 b21 = b21 * det; 919 b22 = b22 * det; 920 b23 = b23 * det; 921 b24 = b24 * det; 922 b31 = b31 * det; 923 b32 = b32 * det; 924 b33 = b33 * det; 925 b34 = b34 * det; 926 b41 = b41 * det; 927 b42 = b42 * det; 928 b43 = b43 * det; 929 b44 = b44 * det; 930 931 inv[0][0] = b11; 932 inv[0][1] = b12; 933 inv[0][2] = b13; 934 inv[0][3] = b14; 935 936 inv[1][0] = b21; 937 inv[1][1] = b22; 938 inv[1][2] = b23; 939 inv[1][3] = b24; 940 941 inv[2][0] = b31; 942 inv[2][1] = b32; 943 inv[2][2] = b33; 944 inv[2][3] = b34; 945 946 inv[3][0] = b41; 947 inv[3][1] = b42; 948 inv[3][2] = b43; 949 inv[3][3] = b44; 950 951 return 1; 952} 953 954 955/*!--------------------------------------------------------------------------* 956 @brief 指定する軸の周りを回転させる回転行列を作成します。 957 958 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 959 @param[in] pAxis 回転軸を指定するベクトルへのポインタ。 960 @param[in] fRad ラジアン単位での回転量 961 962 @return pOut を返します。 963 *---------------------------------------------------------------------------*/ 964NN_MATH_INLINE MTX44* 965MTX44RotAxisRad_C( MTX44* pOut, const VEC3 *pAxis, f32 fRad ) 966{ 967 VEC3 vN; 968 f32 s, c; // sinTheta, cosTheta 969 f32 t; // ( 1 - cosTheta ) 970 f32 x, y, z; // x, y, z components of normalized axis 971 f32 xSq, ySq, zSq; // x, y, z squared 972 973 974 NN_NULL_ASSERT( pOut ); 975 NN_NULL_ASSERT( pAxis ); 976 977 f32 (*const m)[4] = pOut->m; 978 979 s = ::std::sinf(fRad); 980 c = ::std::cosf(fRad); 981 t = 1.0f - c; 982 983 VEC3Normalize( &vN, pAxis ); 984 985 x = vN.x; 986 y = vN.y; 987 z = vN.z; 988 989 xSq = x * x; 990 ySq = y * y; 991 zSq = z * z; 992 993 m[0][0] = ( t * xSq ) + ( c ); 994 m[0][1] = ( t * x * y ) - ( s * z ); 995 m[0][2] = ( t * x * z ) + ( s * y ); 996 m[0][3] = 0.0f; 997 998 m[1][0] = ( t * x * y ) + ( s * z ); 999 m[1][1] = ( t * ySq ) + ( c ); 1000 m[1][2] = ( t * y * z ) - ( s * x ); 1001 m[1][3] = 0.0f; 1002 1003 m[2][0] = ( t * x * z ) - ( s * y ); 1004 m[2][1] = ( t * y * z ) + ( s * x ); 1005 m[2][2] = ( t * zSq ) + ( c ); 1006 m[2][3] = 0.0f; 1007 1008 m[3][0] = 0.0f; 1009 m[3][1] = 0.0f; 1010 m[3][2] = 0.0f; 1011 m[3][3] = 1.0f; 1012 1013 return pOut; 1014} 1015NN_MATH_INLINE MTX44* 1016MTX44RotAxisRad_C_FAST( MTX44* pOut, const VEC3 *pAxis, f32 fRad ) 1017{ 1018 VEC3 vN; 1019 f32 s, c; // sinTheta, cosTheta 1020 f32 t; // ( 1 - cosTheta ) 1021 f32 x, y, z; // x, y, z components of normalized axis 1022 f32 xSq, ySq, zSq; // x, y, z squared 1023 f32 m00, m01, m02, m10, m11, m12, m20, m21, m22; 1024 1025 1026 NN_NULL_ASSERT( pOut ); 1027 NN_NULL_ASSERT( pAxis ); 1028 1029 f32 (*const m)[4] = pOut->m; 1030 1031#if (MTX44ROTAXISRAD__CONFIG == D_FAST_C_ALGO) 1032 SinCosFIdx(&s, &c, NN_MATH_RAD_TO_FIDX(fRad)); 1033#else 1034 s = ::std::sinf(fRad); 1035 c = ::std::cosf(fRad); 1036#endif 1037 t = 1.0f - c; 1038 1039 VEC3Normalize( &vN, pAxis ); 1040 1041 x = vN.x; 1042 y = vN.y; 1043 z = vN.z; 1044 1045 xSq = x * x; 1046 ySq = y * y; 1047 zSq = z * z; 1048 1049 m00 = ( t * xSq ) + ( c ); 1050 m01 = ( t * x * y ) - ( s * z ); 1051 m02 = ( t * x * z ) + ( s * y ); 1052 1053 m10 = ( t * x * y ) + ( s * z ); 1054 m11 = ( t * ySq ) + ( c ); 1055 m12 = ( t * y * z ) - ( s * x ); 1056 1057 m20 = ( t * x * z ) - ( s * y ); 1058 m21 = ( t * y * z ) + ( s * x ); 1059 m22 = ( t * zSq ) + ( c ); 1060 1061 1062 m[0][0] = m00; 1063 m[0][1] = m01; 1064 m[0][2] = m02; 1065 m[0][3] = 0.0f; 1066 1067 m[1][0] = m10; 1068 m[1][1] = m11; 1069 m[1][2] = m12; 1070 m[1][3] = 0.0f; 1071 1072 m[2][0] = m20; 1073 m[2][1] = m21; 1074 m[2][2] = m22; 1075 m[2][3] = 0.0f; 1076 1077 m[3][0] = 0.0f; 1078 m[3][1] = 0.0f; 1079 m[3][2] = 0.0f; 1080 m[3][3] = 1.0f; 1081 1082 return pOut; 1083} 1084 1085 1086/*!--------------------------------------------------------------------------* 1087 @brief 回転行列を作成します。 1088 1089 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 1090 @param[in] fIdxX 1 円周を 256.0 とする単位での X 軸周りの角度 1091 @param[in] fIdxY 1 円周を 256.0 とする単位での Y 軸周りの角度 1092 @param[in] fIdxZ 1 円周を 256.0 とする単位での Z 軸周りの角度 1093 1094 @return pOut を返します。 1095 *---------------------------------------------------------------------------*/ 1096NN_MATH_INLINE MTX44* 1097MTX44RotXYZFIdxC(MTX44* pOut, f32 fIdxX, f32 fIdxY, f32 fIdxZ) 1098{ 1099 NN_FLOAT_ASSERT(fIdxX); 1100 NN_FLOAT_ASSERT(fIdxY); 1101 NN_FLOAT_ASSERT(fIdxZ); 1102 1103 f32 sinx, cosx; 1104 f32 siny, cosy; 1105 f32 sinz, cosz; 1106 f32 f1, f2; 1107 1108 SinCosFIdx(&sinx, &cosx, fIdxX); 1109 SinCosFIdx(&siny, &cosy, fIdxY); 1110 SinCosFIdx(&sinz, &cosz, fIdxZ); 1111 1112 pOut->f._20 = -siny; 1113 pOut->f._00 = cosz * cosy; 1114 pOut->f._10 = sinz * cosy; 1115 pOut->f._21 = cosy * sinx; 1116 pOut->f._22 = cosy * cosx; 1117 1118 f1 = cosx * sinz; 1119 f2 = sinx * cosz; 1120 1121 pOut->f._01 = f2 * siny - f1; 1122 pOut->f._12 = f1 * siny - f2; 1123 1124 f1 = sinx * sinz; 1125 f2 = cosx * cosz; 1126 pOut->f._02 = f2 * siny + f1; 1127 pOut->f._11 = f1 * siny + f2; 1128 1129 pOut->f._03 = 0.f; 1130 pOut->f._13 = 0.f; 1131 pOut->f._23 = 0.f; 1132 1133 pOut->f._30 = 0.0f; 1134 pOut->f._31 = 0.0f; 1135 pOut->f._32 = 0.0f; 1136 pOut->f._33 = 1.0f; 1137 1138 return pOut; 1139} 1140NN_MATH_INLINE MTX44* 1141MTX44RotXYZFIdxC_FAST(MTX44* pOut, f32 fIdxX, f32 fIdxY, f32 fIdxZ) 1142{ 1143 NN_FLOAT_ASSERT(fIdxX); 1144 NN_FLOAT_ASSERT(fIdxY); 1145 NN_FLOAT_ASSERT(fIdxZ); 1146 1147 f32 sinx, cosx; 1148 f32 siny, cosy; 1149 f32 sinz, cosz; 1150 f32 f1, f2, f3, f4; 1151 f32 f00, f10, f21, f22; 1152 f32 f01, f11, f02, f12; 1153 1154 1155 1156 { 1157 1158 u16 idxx; 1159 f32 abs_fidxx; 1160 f32 rx; 1161 1162 u16 idxy; 1163 f32 abs_fidxy; 1164 f32 ry; 1165 1166 u16 idxz; 1167 f32 abs_fidxz; 1168 f32 rz; 1169 1170 int negx, negy, negz; 1171 1172 negx = (fIdxX < 0.0f) ? 1 : 0; 1173 abs_fidxx = FAbs(fIdxX); 1174 negy = (fIdxY < 0.0f) ? 1 : 0; 1175 abs_fidxy = FAbs(fIdxY); 1176 negz = (fIdxZ < 0.0f) ? 1 : 0; 1177 abs_fidxz = FAbs(fIdxZ); 1178 1179 1180 while ( abs_fidxx >= 65536.0f ) 1181 { 1182 abs_fidxx -= 65536.0f; 1183 } 1184 while ( abs_fidxy >= 65536.0f ) 1185 { 1186 abs_fidxy -= 65536.0f; 1187 } 1188 while ( abs_fidxz >= 65536.0f ) 1189 { 1190 abs_fidxz -= 65536.0f; 1191 } 1192 1193 idxx = F32ToU16(abs_fidxx); 1194 idxy = F32ToU16(abs_fidxy); 1195 idxz = F32ToU16(abs_fidxz); 1196 { 1197 f32 idxxf, idxyf, idxzf; 1198 1199 idxxf = U16ToF32(idxx); 1200 idxyf = U16ToF32(idxy); 1201 idxzf = U16ToF32(idxz); 1202 1203 rx = abs_fidxx - idxxf; 1204 ry = abs_fidxy - idxyf; 1205 rz = abs_fidxz - idxzf; 1206 1207 1208 } 1209 1210 idxx &= 0xff; 1211 idxy &= 0xff; 1212 idxz &= 0xff; 1213 1214 { 1215 f32 sinx_val, sinx_delta, cosx_val, cosx_delta; 1216 f32 siny_val, siny_delta, cosy_val, cosy_delta; 1217 f32 sinz_val, sinz_delta, cosz_val, cosz_delta; 1218 1219 sinx_val = internal::gSinCosTbl[idxx].sin_val; 1220 cosx_val = internal::gSinCosTbl[idxx].cos_val; 1221 sinx_delta = internal::gSinCosTbl[idxx].sin_delta; 1222 cosx_delta = internal::gSinCosTbl[idxx].cos_delta; 1223 1224 sinx = sinx_val + rx * sinx_delta; 1225 cosx = cosx_val + rx * cosx_delta; 1226 1227 siny_val = internal::gSinCosTbl[idxy].sin_val; 1228 cosy_val = internal::gSinCosTbl[idxy].cos_val; 1229 siny_delta = internal::gSinCosTbl[idxy].sin_delta; 1230 cosy_delta = internal::gSinCosTbl[idxy].cos_delta; 1231 1232 siny = siny_val + ry * siny_delta; 1233 cosy = cosy_val + ry * cosy_delta; 1234 1235 sinz_val = internal::gSinCosTbl[idxz].sin_val; 1236 cosz_val = internal::gSinCosTbl[idxz].cos_val; 1237 sinz_delta = internal::gSinCosTbl[idxz].sin_delta; 1238 cosz_delta = internal::gSinCosTbl[idxz].cos_delta; 1239 1240 sinz = sinz_val + rz * sinz_delta; 1241 cosz = cosz_val + rz * cosz_delta; 1242 1243 } 1244 1245 sinx = (negx) ? -sinx : sinx; 1246 siny = (negy) ? -siny : siny; 1247 sinz = (negz) ? -sinz : sinz; 1248 1249 } 1250 1251 f00 = cosz * cosy; 1252 f10 = sinz * cosy; 1253 f21 = sinx * cosy; 1254 f22 = cosx * cosy; 1255 1256 f1 = cosx * sinz; 1257 f2 = sinx * cosz; 1258 1259 f01 = f2 * siny - f1; 1260 f12 = f1 * siny - f2; 1261 1262 f3 = sinx * sinz; 1263 f4 = cosx * cosz; 1264 1265 f02 = f4 * siny + f3; 1266 f11 = f3 * siny + f4; 1267 1268 pOut->f._00 = f00; 1269 pOut->f._10 = f10; 1270 pOut->f._21 = f21; 1271 pOut->f._22 = f22; 1272 1273 pOut->f._01 = f01; 1274 pOut->f._12 = f12; 1275 pOut->f._02 = f02; 1276 pOut->f._11 = f11; 1277 pOut->f._20 = -siny; 1278 1279 *(unsigned int*)&pOut->f._03 = 0x00000000; 1280 *(unsigned int*)&pOut->f._13 = 0x00000000; 1281 *(unsigned int*)&pOut->f._23 = 0x00000000; 1282 1283 *(unsigned int*)&pOut->f._30 = 0x00000000; 1284 *(unsigned int*)&pOut->f._31 = 0x00000000; 1285 *(unsigned int*)&pOut->f._32 = 0x00000000; 1286 *(unsigned int*)&pOut->f._33 = 0x3F800000; 1287 1288 return pOut; 1289} 1290 1291/*!--------------------------------------------------------------------------* 1292 @brief スケール変換用の行列を作成します。 1293 1294 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 1295 @param[in] pS それぞれの軸方向のスケール値が格納されたベクトルへのポインタ。 1296 1297 @return pOut を返します。 1298 *---------------------------------------------------------------------------*/ 1299NN_MATH_INLINE MTX44* 1300MTX44ScaleC(MTX44* pOut, const VEC3* pS) 1301{ 1302 NN_NULL_ASSERT( pOut ); 1303 NN_NULL_ASSERT( pS ); 1304 1305 f32 (*const m)[4] = pOut->m; 1306 1307 m[0][0] = pS->x; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f; 1308 m[1][0] = 0.0f; m[1][1] = pS->y; m[1][2] = 0.0f; m[1][3] = 0.0f; 1309 m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = pS->z; m[2][3] = 0.0f; 1310 m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f; 1311 1312 return pOut; 1313} 1314NN_MATH_INLINE MTX44* 1315MTX44ScaleC_FAST(MTX44* pOut, const VEC3* pS) 1316{ 1317 NN_NULL_ASSERT( pOut ); 1318 NN_NULL_ASSERT( pS ); 1319 1320 unsigned int *m = reinterpret_cast<unsigned int *>(pOut->m); 1321 1322 f32 f1 = 1.0f; 1323 f32 f0 = 0.0f; 1324 const unsigned int f32_1 = *(reinterpret_cast<unsigned int*>(&f1)); 1325 const unsigned int f32_0 = *(reinterpret_cast<unsigned int*>(&f0)); 1326 const unsigned int *p = reinterpret_cast<const unsigned int*>(pS); 1327 1328 m[ 0] = p[0]; m[ 1] = f32_0; m[ 2] = f32_0; m[ 3] = f32_0; 1329 m[ 4] = f32_0; m[ 5] = p[1]; m[ 6] = f32_0; m[ 7] = f32_0; 1330 m[ 8] = f32_0; m[ 9] = f32_0; m[10] = p[2]; m[11] = f32_0; 1331 m[12] = f32_0; m[13] = f32_0; m[14] = f32_0; m[15] = f32_1; 1332 1333 return pOut; 1334} 1335 1336 1337/*!--------------------------------------------------------------------------* 1338 @brief 行列にスケール変換を適用します。スケール行列を右から掛けます。 1339 1340 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 1341 @param[in] pM 元となる行列へのポインタ。 1342 @param[in] pS それぞれの軸方向のスケール値が格納されたベクトルへのポインタ。 1343 1344 @return pOut を返します。 1345 *---------------------------------------------------------------------------*/ 1346NN_MATH_INLINE MTX44* 1347MTX44MultScaleC(MTX44* pOut, const MTX44* pM, const VEC3* pS) 1348{ 1349 // スケール行列を右からかけるバージョン 1350 pOut->f._00 = pM->f._00 * pS->x; 1351 pOut->f._10 = pM->f._10 * pS->x; 1352 pOut->f._20 = pM->f._20 * pS->x; 1353 1354 pOut->f._01 = pM->f._01 * pS->y; 1355 pOut->f._11 = pM->f._11 * pS->y; 1356 pOut->f._21 = pM->f._21 * pS->y; 1357 1358 pOut->f._02 = pM->f._02 * pS->z; 1359 pOut->f._12 = pM->f._12 * pS->z; 1360 pOut->f._22 = pM->f._22 * pS->z; 1361 1362 if (pOut != pM) 1363 { 1364 pOut->f._03 = pM->f._03; 1365 pOut->f._13 = pM->f._13; 1366 pOut->f._23 = pM->f._23; 1367 } 1368 1369 return pOut; 1370} 1371 1372 1373/*!--------------------------------------------------------------------------* 1374 @brief 行列にスケール変換を適用します。スケール行列を左から掛けます。 1375 1376 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 1377 @param[in] pS それぞれの軸方向のスケール値が格納されたベクトルへのポインタ。 1378 @param[in] pM 元となる行列へのポインタ。 1379 1380 @return pOut を返します。 1381 *---------------------------------------------------------------------------*/ 1382NN_MATH_INLINE MTX44* 1383MTX44MultScaleC(MTX44* pOut, const VEC3* pS, const MTX44* pM) 1384{ 1385 NN_NULL_ASSERT( pOut ); 1386 NN_NULL_ASSERT( pS ); 1387 NN_NULL_ASSERT( pM ); 1388 1389 const f32 (*const src)[4] = pM->m; 1390 f32 (*const dst)[4] = pOut->m; 1391 1392 dst[0][0] = src[0][0] * pS->x; dst[0][1] = src[0][1] * pS->x; 1393 dst[0][2] = src[0][2] * pS->x; dst[0][3] = src[0][3] * pS->x; 1394 1395 dst[1][0] = src[1][0] * pS->y; dst[1][1] = src[1][1] * pS->y; 1396 dst[1][2] = src[1][2] * pS->y; dst[1][3] = src[1][3] * pS->y; 1397 1398 dst[2][0] = src[2][0] * pS->z; dst[2][1] = src[2][1] * pS->z; 1399 dst[2][2] = src[2][2] * pS->z; dst[2][3] = src[2][3] * pS->z; 1400 1401 return pOut; 1402} 1403 1404 1405/*!--------------------------------------------------------------------------* 1406 @brief 平行移動用の行列を作成します。 1407 1408 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 1409 @param[in] pT それぞれの軸方向の移動量が格納されたベクトルへのポインタ。 1410 1411 @return pOut を返します。 1412 *---------------------------------------------------------------------------*/ 1413NN_MATH_INLINE MTX44* 1414MTX44TranslateC(MTX44* pOut, const VEC3* pT) 1415{ 1416 NN_NULL_ASSERT( pOut ); 1417 NN_NULL_ASSERT( pT ); 1418 1419 f32 (*const m)[4] = pOut->m; 1420 1421 m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = pT->x; 1422 m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = pT->y; 1423 m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = pT->z; 1424 m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f; 1425 1426 return pOut; 1427} 1428NN_MATH_INLINE MTX44* 1429MTX44TranslateC_FAST(MTX44* pOut, const VEC3* pT) 1430{ 1431 NN_NULL_ASSERT( pOut ); 1432 NN_NULL_ASSERT( pT ); 1433 1434 unsigned int *m = reinterpret_cast<unsigned int *>(pOut->m); 1435 1436 f32 f1 = 1.0f; 1437 f32 f0 = 0.0f; 1438 const unsigned int f32_1 = *(reinterpret_cast<unsigned int*>(&f1)); 1439 const unsigned int f32_0 = *(reinterpret_cast<unsigned int*>(&f0)); 1440 const unsigned int *p = reinterpret_cast<const unsigned int*>(pT); 1441 1442 m[ 0] = f32_1; m[ 1] = f32_0; m[ 2] = f32_0; m[ 3] = p[0]; 1443 m[ 4] = f32_0; m[ 5] = f32_1; m[ 6] = f32_0; m[ 7] = p[1]; 1444 m[ 8] = f32_0; m[ 9] = f32_0; m[10] = f32_1; m[11] = p[2]; 1445 m[12] = f32_0; m[13] = f32_0; m[14] = f32_0; m[15] = f32_1; 1446 1447 return pOut; 1448} 1449 1450 1451/*!--------------------------------------------------------------------------* 1452 @brief 行列に平行移動を適用します。移動行列を左から掛けます。 1453 1454 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 1455 @param[in] pT それぞれの軸方向の移動量が格納されたベクトルへのポインタ。 1456 @param[in] pM 元となる行列へのポインタ。 1457 1458 @return pOut を返します。 1459 *---------------------------------------------------------------------------*/ 1460NN_MATH_INLINE MTX44* 1461MTX44MultTranslateC(MTX44* pOut, const VEC3* pT, const MTX44* pM) 1462{ 1463 NN_NULL_ASSERT(pOut); 1464 NN_NULL_ASSERT(pT); 1465 NN_NULL_ASSERT(pM); 1466 1467 const f32 (*const src)[4] = pM->m; 1468 f32 (*const dst)[4] = pOut->m; 1469 1470 if ( src != dst ) 1471 { 1472 dst[0][0] = src[0][0]; dst[0][1] = src[0][1]; dst[0][2] = src[0][2]; 1473 dst[1][0] = src[1][0]; dst[1][1] = src[1][1]; dst[1][2] = src[1][2]; 1474 dst[2][0] = src[2][0]; dst[2][1] = src[2][1]; dst[2][2] = src[2][2]; 1475 } 1476 1477 dst[0][3] = src[0][3] + pT->x; 1478 dst[1][3] = src[1][3] + pT->y; 1479 dst[2][3] = src[2][3] + pT->z; 1480 1481 return pOut; 1482} 1483 1484/*!--------------------------------------------------------------------------* 1485 @brief 行列に平行移動を適用します。移動行列を右から掛けます。 1486 1487 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 1488 @param[in] pM 元となる行列へのポインタ。 1489 @param[in] pT それぞれの軸方向の移動量が格納されたベクトルへのポインタ。 1490 1491 @return pOut を返します。 1492 *---------------------------------------------------------------------------*/ 1493NN_MATH_INLINE MTX44* 1494MTX44MultTranslateC(MTX44* pOut, const MTX44* pM, const VEC3* pT) 1495{ 1496 NN_NULL_ASSERT(pOut); 1497 NN_NULL_ASSERT(pT); 1498 NN_NULL_ASSERT(pM); 1499 1500 // pOut = pM * pT 1501 if (pOut != pM) 1502 { 1503 (void)MTX44Copy(pOut, pM); 1504 } 1505 1506 VEC4 tmp; 1507 VEC3Transform(&tmp, pM, pT); 1508 1509 pOut->f._03 = tmp.x; 1510 pOut->f._13 = tmp.y; 1511 pOut->f._23 = tmp.z; 1512 1513 return pOut; 1514} 1515 1516/*! 1517 @} 1518*/ 1519 1520} // namespace ARMv6 1521} // namespace math 1522} // namespace nn 1523