1/*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: math_Matrix34.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: 13664 $ 14 *---------------------------------------------------------------------------*/ 15#include <cmath> 16#include <nn/math/math_Vector3.h> 17 18namespace nn { 19namespace math { 20namespace ARMv6 { 21/*! 22 @name ユーティリティ 23 @{ 24*/ 25 26/*!--------------------------------------------------------------------------* 27 @brief ベクトルを行列で変換します。ベクトルの 4 要素目を 1 として計算します。 28 29 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 30 pV と同じベクトルを指していても構いません。 31 @param[in] pM 変換行列へのポインタ。 32 @param[in] pV 元となるベクトルへのポインタ。 33 34 @return pOut を返します。 35 *---------------------------------------------------------------------------*/ 36NN_MATH_INLINE VEC3* 37VEC3TransformC(VEC3* pOut, const MTX34* __restrict pM, const VEC3* __restrict pV) 38{ 39 NN_NULL_ASSERT( pM ); 40 NN_NULL_ASSERT( pV ); 41 NN_NULL_ASSERT( pOut ); 42 43 VEC3 vTmp; 44 VEC3* pDst = (pOut == pV) ? &vTmp : pOut; 45 46 pDst->x = pM->f._00 * pV->x + pM->f._01 * pV->y + pM->f._02 * pV->z + pM->f._03; 47 pDst->y = pM->f._10 * pV->x + pM->f._11 * pV->y + pM->f._12 * pV->z + pM->f._13; 48 pDst->z = pM->f._20 * pV->x + pM->f._21 * pV->y + pM->f._22 * pV->z + pM->f._23; 49 50 if (pDst == &vTmp) 51 { 52 pOut->x = pDst->x; 53 pOut->y = pDst->y; 54 pOut->z = pDst->z; 55 } 56 57 return pOut; 58} 59 60/* ------------------------------------------------------------------------ 61 MTX34 62 ------------------------------------------------------------------------ */ 63 64/*! 65 @name 行列 66 @{ 67*/ 68 69/*!--------------------------------------------------------------------------* 70 @brief 行列をコピーします。 71 72 @param[out] pOut コピー先の行列へのポインタ。 73 @param[in] p コピー元の行列へのポインタ 74 75 @return pOut を返します。 76 *---------------------------------------------------------------------------*/ 77NN_MATH_INLINE MTX34* 78MTX34CopyC(MTX34* pOut, const MTX34* p) 79{ 80 NN_NULL_ASSERT( pOut ); 81 NN_NULL_ASSERT( p ); 82 83 if ( p != pOut ) 84 { 85 *pOut = *p; 86 } 87 88 return pOut; 89} 90 91 92 93/*!--------------------------------------------------------------------------* 94 @brief 行列の積を計算します。 95 96 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 97 p1, p2 と同じ行列を指していても構いません。 98 @param[in] p1 左辺値へのポインタ。 99 @param[in] p2 右辺値へのポインタ。 100 101 @return pOut を返します。 102 *---------------------------------------------------------------------------*/ 103NN_MATH_INLINE MTX34* 104MTX34MultC(MTX34* pOut, const MTX34* __restrict p1, const MTX34* __restrict p2) 105{ 106 MTX34 mTmp; 107 108 NN_NULL_ASSERT( pOut ); 109 NN_NULL_ASSERT( p1 ); 110 NN_NULL_ASSERT( p2 ); 111 112 MTX34* __restrict pDst = (pOut == p1 || pOut == p2) ? &mTmp : pOut; 113 114 pDst->f._00 = p1->f._00 * p2->f._00 + p1->f._01 * p2->f._10 + p1->f._02 * p2->f._20; 115 pDst->f._01 = p1->f._00 * p2->f._01 + p1->f._01 * p2->f._11 + p1->f._02 * p2->f._21; 116 pDst->f._02 = p1->f._00 * p2->f._02 + p1->f._01 * p2->f._12 + p1->f._02 * p2->f._22; 117 pDst->f._03 = p1->f._00 * p2->f._03 + p1->f._01 * p2->f._13 + p1->f._02 * p2->f._23 + p1->f._03; 118 119 pDst->f._10 = p1->f._10 * p2->f._00 + p1->f._11 * p2->f._10 + p1->f._12 * p2->f._20; 120 pDst->f._11 = p1->f._10 * p2->f._01 + p1->f._11 * p2->f._11 + p1->f._12 * p2->f._21; 121 pDst->f._12 = p1->f._10 * p2->f._02 + p1->f._11 * p2->f._12 + p1->f._12 * p2->f._22; 122 pDst->f._13 = p1->f._10 * p2->f._03 + p1->f._11 * p2->f._13 + p1->f._12 * p2->f._23 + p1->f._13; 123 124 pDst->f._20 = p1->f._20 * p2->f._00 + p1->f._21 * p2->f._10 + p1->f._22 * p2->f._20; 125 pDst->f._21 = p1->f._20 * p2->f._01 + p1->f._21 * p2->f._11 + p1->f._22 * p2->f._21; 126 pDst->f._22 = p1->f._20 * p2->f._02 + p1->f._21 * p2->f._12 + p1->f._22 * p2->f._22; 127 pDst->f._23 = p1->f._20 * p2->f._03 + p1->f._21 * p2->f._13 + p1->f._22 * p2->f._23 + p1->f._23; 128 129 // overwrite a or b if needed 130 if ( pDst == &mTmp ) 131 { 132 MTX34Copy( pOut, &mTmp ); 133 } 134 135 return pOut; 136} 137 138/*!--------------------------------------------------------------------------* 139 @brief 行列の和を計算します。 140 141 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。 142 @param[in] p1 左辺値へのポインタ。 143 @param[in] p2 右辺値へのポインタ。 144 145 @return pOut を返します。 146 *---------------------------------------------------------------------------*/ 147NN_MATH_INLINE MTX34* 148MTX34AddC(MTX34* pOut, const MTX34* p1, const MTX34* p2) 149{ 150 pOut->f._00 = p1->f._00 + p2->f._00; 151 pOut->f._01 = p1->f._01 + p2->f._01; 152 pOut->f._02 = p1->f._02 + p2->f._02; 153 pOut->f._03 = p1->f._03 + p2->f._03; 154 155 pOut->f._10 = p1->f._10 + p2->f._10; 156 pOut->f._11 = p1->f._11 + p2->f._11; 157 pOut->f._12 = p1->f._12 + p2->f._12; 158 pOut->f._13 = p1->f._13 + p2->f._13; 159 160 pOut->f._20 = p1->f._20 + p2->f._20; 161 pOut->f._21 = p1->f._21 + p2->f._21; 162 pOut->f._22 = p1->f._22 + p2->f._22; 163 pOut->f._23 = p1->f._23 + p2->f._23; 164 165 return pOut; 166} 167 168/*!--------------------------------------------------------------------------* 169 @brief 行列のスカラー積を計算します。 170 171 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じ行列を指していても構いません。 172 @param[in] p 元の行列のポインタ。 173 @param[in] f 掛ける数 174 175 @return pOut を返します。 176 *---------------------------------------------------------------------------*/ 177NN_MATH_INLINE MTX34* 178MTX34MultC(MTX34* pOut, const MTX34* p, f32 f) 179{ 180 pOut->f._00 = p->f._00 * f; 181 pOut->f._01 = p->f._01 * f; 182 pOut->f._02 = p->f._02 * f; 183 pOut->f._03 = p->f._03 * f; 184 185 pOut->f._10 = p->f._10 * f; 186 pOut->f._11 = p->f._11 * f; 187 pOut->f._12 = p->f._12 * f; 188 pOut->f._13 = p->f._13 * f; 189 190 pOut->f._20 = p->f._20 * f; 191 pOut->f._21 = p->f._21 * f; 192 pOut->f._22 = p->f._22 * f; 193 pOut->f._23 = p->f._23 * f; 194 195 return pOut; 196} 197 198 199/*!--------------------------------------------------------------------------* 200 @brief スケール変換用の行列を作成します。 201 202 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 203 @param[in] pS それぞれの軸方向のスケール値が格納されたベクトルへのポインタ。 204 205 @return pOut を返します。 206 *---------------------------------------------------------------------------*/ 207NN_MATH_INLINE MTX34* 208MTX34ScaleC(MTX34* pOut, const VEC3* pS) 209{ 210 NN_NULL_ASSERT( pOut ); 211 NN_NULL_ASSERT( pS ); 212 213 f32 (*const m)[4] = pOut->m; 214 215 m[0][0] = pS->x; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f; 216 m[1][0] = 0.0f; m[1][1] = pS->y; m[1][2] = 0.0f; m[1][3] = 0.0f; 217 m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = pS->z; m[2][3] = 0.0f; 218 219 return pOut; 220} 221NN_MATH_INLINE MTX34* 222MTX34ScaleC_FAST(MTX34* pOut, const VEC3* pS) 223{ 224 NN_NULL_ASSERT( pOut ); 225 NN_NULL_ASSERT( pS ); 226 227 f32 f0 = 0.0f; 228 const unsigned int f32_0 = *(reinterpret_cast<unsigned int*>(&f0)); 229 unsigned int *m = reinterpret_cast<unsigned int *>(pOut->m); 230 const unsigned int *p = reinterpret_cast<const unsigned int*>(pS); 231 232 m[ 0] = p[0]; m[ 1] = f32_0; m[ 2] = f32_0; m[ 3] = f32_0; 233 m[ 4] = f32_0; m[ 5] = p[1]; m[ 6] = f32_0; m[ 7] = f32_0; 234 m[ 8] = f32_0; m[ 9] = f32_0; m[10] = p[2]; m[11] = f32_0; 235 236 return pOut; 237} 238 239/*!--------------------------------------------------------------------------* 240 @brief 行列にスケール変換を適用します。スケール行列を右から掛けます。 241 242 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 243 @param[in] pM 元となる行列へのポインタ。 244 @param[in] pS それぞれの軸方向のスケール値が格納されたベクトルへのポインタ。 245 246 @return pOut を返します。 247 *---------------------------------------------------------------------------*/ 248NN_MATH_INLINE MTX34* 249MTX34MultScaleC(MTX34* pOut, const MTX34* pM, const VEC3* pS) 250{ 251 // スケール行列を右からかけるバージョン 252 pOut->f._00 = pM->f._00 * pS->x; 253 pOut->f._10 = pM->f._10 * pS->x; 254 pOut->f._20 = pM->f._20 * pS->x; 255 256 pOut->f._01 = pM->f._01 * pS->y; 257 pOut->f._11 = pM->f._11 * pS->y; 258 pOut->f._21 = pM->f._21 * pS->y; 259 260 pOut->f._02 = pM->f._02 * pS->z; 261 pOut->f._12 = pM->f._12 * pS->z; 262 pOut->f._22 = pM->f._22 * pS->z; 263 264 if (pOut != pM) 265 { 266 pOut->f._03 = pM->f._03; 267 pOut->f._13 = pM->f._13; 268 pOut->f._23 = pM->f._23; 269 } 270 271 return pOut; 272} 273 274 275/*!--------------------------------------------------------------------------* 276 @brief 行列にスケール変換を適用します。スケール行列を左から掛けます。 277 278 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 279 @param[in] pS それぞれの軸方向のスケール値が格納されたベクトルへのポインタ。 280 @param[in] pM 元となる行列へのポインタ。 281 282 @return pOut を返します。 283 *---------------------------------------------------------------------------*/ 284NN_MATH_INLINE MTX34* 285MTX34MultScaleC(MTX34* pOut, const VEC3* __restrict pS, const MTX34* pM) 286{ 287 NN_NULL_ASSERT( pOut ); 288 NN_NULL_ASSERT( pS ); 289 NN_NULL_ASSERT( pM ); 290 291 const f32 (*const src)[4] = pM->m; 292 f32 (*const dst)[4] = pOut->m; 293 294 dst[0][0] = src[0][0] * pS->x; dst[0][1] = src[0][1] * pS->x; 295 dst[0][2] = src[0][2] * pS->x; dst[0][3] = src[0][3] * pS->x; 296 297 dst[1][0] = src[1][0] * pS->y; dst[1][1] = src[1][1] * pS->y; 298 dst[1][2] = src[1][2] * pS->y; dst[1][3] = src[1][3] * pS->y; 299 300 dst[2][0] = src[2][0] * pS->z; dst[2][1] = src[2][1] * pS->z; 301 dst[2][2] = src[2][2] * pS->z; dst[2][3] = src[2][3] * pS->z; 302 303 return pOut; 304} 305 306 307/*!--------------------------------------------------------------------------* 308 @brief 平行移動用の行列を作成します。 309 310 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 311 @param[in] pT それぞれの軸方向の移動量が格納されたベクトルへのポインタ。 312 313 @return pOut を返します。 314 *---------------------------------------------------------------------------*/ 315NN_MATH_INLINE MTX34* 316MTX34TranslateC(MTX34* pOut, const VEC3* pT) 317{ 318 NN_NULL_ASSERT( pOut ); 319 NN_NULL_ASSERT( pT ); 320 321 f32 (*const m)[4] = pOut->m; 322 323 m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = pT->x; 324 m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = pT->y; 325 m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = pT->z; 326 327 return pOut; 328} 329NN_MATH_INLINE MTX34* 330MTX34TranslateC_FAST(MTX34* pOut, const VEC3* pT) 331{ 332 NN_NULL_ASSERT( pOut ); 333 NN_NULL_ASSERT( pT ); 334 335 unsigned int *m = reinterpret_cast<unsigned int *>(pOut->m); 336 337 f32 f1 = 1.0f; 338 f32 f0 = 0.0f; 339 const unsigned int f32_1 = *(reinterpret_cast<unsigned int*>(&f1)); 340 const unsigned int f32_0 = *(reinterpret_cast<unsigned int*>(&f0)); 341 const unsigned int *p = reinterpret_cast<const unsigned int*>(pT); 342 343 m[ 0] = f32_1; m[ 1] = f32_0; m[ 2] = f32_0; m[ 3] = p[0]; 344 m[ 4] = f32_0; m[ 5] = f32_1; m[ 6] = f32_0; m[ 7] = p[1]; 345 m[ 8] = f32_0; m[ 9] = f32_0; m[10] = f32_1; m[11] = p[2]; 346 347 return pOut; 348} 349 350/*!--------------------------------------------------------------------------* 351 @brief 行列に平行移動を適用します。移動行列を左から掛けます。 352 353 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 354 @param[in] pT それぞれの軸方向の移動量が格納されたベクトルへのポインタ。 355 @param[in] pM 元となる行列へのポインタ。 356 357 @return pOut を返します。 358 *---------------------------------------------------------------------------*/ 359NN_MATH_INLINE MTX34* 360MTX34MultTranslateC(MTX34* pOut, const VEC3* pT, const MTX34* pM) 361{ 362 NN_NULL_ASSERT(pOut); 363 NN_NULL_ASSERT(pT); 364 NN_NULL_ASSERT(pM); 365 366 const f32 (*const src)[4] = pM->m; 367 f32 (*const dst)[4] = pOut->m; 368 369 if ( src != dst ) 370 { 371 dst[0][0] = src[0][0]; dst[0][1] = src[0][1]; dst[0][2] = src[0][2]; 372 dst[1][0] = src[1][0]; dst[1][1] = src[1][1]; dst[1][2] = src[1][2]; 373 dst[2][0] = src[2][0]; dst[2][1] = src[2][1]; dst[2][2] = src[2][2]; 374 } 375 376 dst[0][3] = src[0][3] + pT->x; 377 dst[1][3] = src[1][3] + pT->y; 378 dst[2][3] = src[2][3] + pT->z; 379 380 return pOut; 381} 382 383/*!--------------------------------------------------------------------------* 384 @brief 行列に平行移動を適用します。移動行列を右から掛けます。 385 386 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pM と同じ行列を指していても構いません。 387 @param[in] pM 元となる行列へのポインタ。 388 @param[in] pT それぞれの軸方向の移動量が格納されたベクトルへのポインタ。 389 390 @return pOut を返します。 391 *---------------------------------------------------------------------------*/ 392NN_MATH_INLINE MTX34* 393MTX34MultTranslateC(MTX34* pOut, const MTX34* pM, const VEC3* pT) 394{ 395 // pOut = pM * pT 396 if (pOut != pM) 397 { 398 (void)MTX34Copy(pOut, pM); 399 } 400 401 VEC3 tmp; 402 VEC3Transform(&tmp, pM, pT); 403 404 pOut->f._03 = tmp.x; 405 pOut->f._13 = tmp.y; 406 pOut->f._23 = tmp.z; 407 408 return pOut; 409} 410 411 412 413/*!--------------------------------------------------------------------------* 414 @brief 行列を実数倍して、別の行列を足します。 415 416 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。 417 @param[in] t 掛ける数。 418 @param[in] p1 元の行列へのポインタ。 419 @param[in] p2 足す行列へのポインタ。 420 421 @return pOut を返します。 422 *---------------------------------------------------------------------------*/ 423NN_MATH_INLINE MTX34* 424MTX34MAddC(MTX34* pOut, f32 t, const MTX34* p1, const MTX34* p2) 425{ 426 pOut->f._00 = t * p1->f._00 + p2->f._00; 427 pOut->f._01 = t * p1->f._01 + p2->f._01; 428 pOut->f._02 = t * p1->f._02 + p2->f._02; 429 pOut->f._03 = t * p1->f._03 + p2->f._03; 430 431 pOut->f._10 = t * p1->f._10 + p2->f._10; 432 pOut->f._11 = t * p1->f._11 + p2->f._11; 433 pOut->f._12 = t * p1->f._12 + p2->f._12; 434 pOut->f._13 = t * p1->f._13 + p2->f._13; 435 436 pOut->f._20 = t * p1->f._20 + p2->f._20; 437 pOut->f._21 = t * p1->f._21 + p2->f._21; 438 pOut->f._22 = t * p1->f._22 + p2->f._22; 439 pOut->f._23 = t * p1->f._23 + p2->f._23; 440 441 return pOut; 442} 443 444 445/*!--------------------------------------------------------------------------* 446 @brief 指定する軸の周りを回転させる回転行列を作成します。 447 448 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 449 @param[in] pAxis 回転軸を指定するベクトルへのポインタ。 450 @param[in] fRad ラジアン単位での回転量 451 452 @return pOut を返します。 453 *---------------------------------------------------------------------------*/ 454NN_MATH_INLINE MTX34* 455MTX34RotAxisRad_C( MTX34* pOut, const VEC3 *pAxis, f32 fRad ) 456{ 457 VEC3 vN; 458 f32 s, c; // sinTheta, cosTheta 459 f32 t; // ( 1 - cosTheta ) 460 f32 x, y, z; // x, y, z components of normalized axis 461 f32 xSq, ySq, zSq; // x, y, z squared 462 463 464 NN_NULL_ASSERT( pOut ); 465 NN_NULL_ASSERT( pAxis ); 466 467 f32 (*const m)[4] = pOut->m; 468 469 s = ::std::sinf(fRad); 470 c = ::std::cosf(fRad); 471 t = 1.0f - c; 472 473 VEC3Normalize( &vN, pAxis ); 474 475 x = vN.x; 476 y = vN.y; 477 z = vN.z; 478 479 xSq = x * x; 480 ySq = y * y; 481 zSq = z * z; 482 483 m[0][0] = ( t * xSq ) + ( c ); 484 m[0][1] = ( t * x * y ) - ( s * z ); 485 m[0][2] = ( t * x * z ) + ( s * y ); 486 m[0][3] = 0.0f; 487 488 m[1][0] = ( t * x * y ) + ( s * z ); 489 m[1][1] = ( t * ySq ) + ( c ); 490 m[1][2] = ( t * y * z ) - ( s * x ); 491 m[1][3] = 0.0f; 492 493 m[2][0] = ( t * x * z ) - ( s * y ); 494 m[2][1] = ( t * y * z ) + ( s * x ); 495 m[2][2] = ( t * zSq ) + ( c ); 496 m[2][3] = 0.0f; 497 498 return pOut; 499} 500NN_MATH_INLINE MTX34* 501MTX34RotAxisRad_C_FAST( MTX34* pOut, const VEC3 *pAxis, f32 fRad ) 502{ 503 VEC3 vN; 504 f32 s, c; // sinTheta, cosTheta 505 f32 t; // ( 1 - cosTheta ) 506 f32 x, y, z; // x, y, z components of normalized axis 507 f32 xSq, ySq, zSq; // x, y, z squared 508 509 510 NN_NULL_ASSERT( pOut ); 511 NN_NULL_ASSERT( pAxis ); 512 513 f32 (*const m)[4] = pOut->m; 514 515#if (MTX34ROTAXISRAD__CONFIG == D_FAST_C_ALGO) 516 SinCosFIdx(&s, &c, NN_MATH_RAD_TO_FIDX(fRad)); 517#else 518 s = ::std::sinf(fRad); 519 c = ::std::cosf(fRad); 520#endif 521 t = 1.0f - c; 522 523 VEC3Normalize( &vN, pAxis ); 524 525 x = vN.x; 526 y = vN.y; 527 z = vN.z; 528 529 xSq = x * x; 530 ySq = y * y; 531 zSq = z * z; 532 533 register f32 m00, m01, m02, m10, m11, m12, m20, m21, m22; 534 m00 = ( t * xSq ) + ( c ); 535 m01 = ( t * x * y ) - ( s * z ); 536 m02 = ( t * x * z ) + ( s * y ); 537 538 m10 = ( t * x * y ) + ( s * z ); 539 m11 = ( t * ySq ) + ( c ); 540 m12 = ( t * y * z ) - ( s * x ); 541 542 m20 = ( t * x * z ) - ( s * y ); 543 m21 = ( t * y * z ) + ( s * x ); 544 m22 = ( t * zSq ) + ( c ); 545 546 m[0][0] = m00; 547 m[0][1] = m01; 548 m[0][2] = m02; 549 m[0][3] = 0.0f; 550 551 m[1][0] = m10; 552 m[1][1] = m11; 553 m[1][2] = m12; 554 m[1][3] = 0.0f; 555 556 m[2][0] = m20; 557 m[2][1] = m21; 558 m[2][2] = m22; 559 m[2][3] = 0.0f; 560 561 562 return pOut; 563} 564 565/*!--------------------------------------------------------------------------* 566 @brief 回転行列を作成します。 567 568 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 569 @param[in] fIdxX 1 円周を 256.0 とする単位での X 軸周りの角度 570 @param[in] fIdxY 1 円周を 256.0 とする単位での Y 軸周りの角度 571 @param[in] fIdxZ 1 円周を 256.0 とする単位での Z 軸周りの角度 572 573 @return pOut を返します。 574 *---------------------------------------------------------------------------*/ 575NN_MATH_INLINE MTX34* 576MTX34RotXYZFIdxC(MTX34* pOut, f32 fIdxX, f32 fIdxY, f32 fIdxZ) 577{ 578 NN_FLOAT_ASSERT(fIdxX); 579 NN_FLOAT_ASSERT(fIdxY); 580 NN_FLOAT_ASSERT(fIdxZ); 581 582 f32 sinx, cosx; 583 f32 siny, cosy; 584 f32 sinz, cosz; 585 f32 f1, f2; 586 587 SinCosFIdx(&sinx, &cosx, fIdxX); 588 SinCosFIdx(&siny, &cosy, fIdxY); 589 SinCosFIdx(&sinz, &cosz, fIdxZ); 590 591 pOut->f._20 = -siny; 592 pOut->f._00 = cosz * cosy; 593 pOut->f._10 = sinz * cosy; 594 pOut->f._21 = cosy * sinx; 595 pOut->f._22 = cosy * cosx; 596 597 f1 = cosx * sinz; 598 f2 = sinx * cosz; 599 600 pOut->f._01 = f2 * siny - f1; 601 pOut->f._12 = f1 * siny - f2; 602 603 f1 = sinx * sinz; 604 f2 = cosx * cosz; 605 pOut->f._02 = f2 * siny + f1; 606 pOut->f._11 = f1 * siny + f2; 607 608 pOut->f._03 = 0.f; 609 pOut->f._13 = 0.f; 610 pOut->f._23 = 0.f; 611 612 return pOut; 613} 614NN_MATH_INLINE MTX34* 615MTX34RotXYZFIdxC_FAST(MTX34* pOut, f32 fIdxX, f32 fIdxY, f32 fIdxZ) 616{ 617 NN_FLOAT_ASSERT(fIdxX); 618 NN_FLOAT_ASSERT(fIdxY); 619 NN_FLOAT_ASSERT(fIdxZ); 620 621 f32 sinx, cosx; 622 f32 siny, cosy; 623 f32 sinz, cosz; 624 f32 f1, f2, f3, f4; 625 f32 f00, f10, f21, f22; 626 f32 f01, f11, f02, f12; 627 628 629 630 { 631 632 u16 idxx; 633 f32 abs_fidxx; 634 f32 rx; 635 636 u16 idxy; 637 f32 abs_fidxy; 638 f32 ry; 639 640 u16 idxz; 641 f32 abs_fidxz; 642 f32 rz; 643 644 int negx, negy, negz; 645 646 negx = (fIdxX < 0.0f) ? 1 : 0; 647 abs_fidxx = FAbs(fIdxX); 648 negy = (fIdxY < 0.0f) ? 1 : 0; 649 abs_fidxy = FAbs(fIdxY); 650 negz = (fIdxZ < 0.0f) ? 1 : 0; 651 abs_fidxz = FAbs(fIdxZ); 652 653 654 while ( abs_fidxx >= 65536.0f ) 655 { 656 abs_fidxx -= 65536.0f; 657 } 658 while ( abs_fidxy >= 65536.0f ) 659 { 660 abs_fidxy -= 65536.0f; 661 } 662 while ( abs_fidxz >= 65536.0f ) 663 { 664 abs_fidxz -= 65536.0f; 665 } 666 667 idxx = F32ToU16(abs_fidxx); 668 idxy = F32ToU16(abs_fidxy); 669 idxz = F32ToU16(abs_fidxz); 670 { 671 f32 idxxf, idxyf, idxzf; 672 673 idxxf = U16ToF32(idxx); 674 idxyf = U16ToF32(idxy); 675 idxzf = U16ToF32(idxz); 676 677 rx = abs_fidxx - idxxf; 678 ry = abs_fidxy - idxyf; 679 rz = abs_fidxz - idxzf; 680 681 682 } 683 684 idxx &= 0xff; 685 idxy &= 0xff; 686 idxz &= 0xff; 687 688 { 689 f32 sinx_val, sinx_delta, cosx_val, cosx_delta; 690 f32 siny_val, siny_delta, cosy_val, cosy_delta; 691 f32 sinz_val, sinz_delta, cosz_val, cosz_delta; 692 693 sinx_val = internal::gSinCosTbl[idxx].sin_val; 694 cosx_val = internal::gSinCosTbl[idxx].cos_val; 695 sinx_delta = internal::gSinCosTbl[idxx].sin_delta; 696 cosx_delta = internal::gSinCosTbl[idxx].cos_delta; 697 698 sinx = sinx_val + rx * sinx_delta; 699 cosx = cosx_val + rx * cosx_delta; 700 701 siny_val = internal::gSinCosTbl[idxy].sin_val; 702 cosy_val = internal::gSinCosTbl[idxy].cos_val; 703 siny_delta = internal::gSinCosTbl[idxy].sin_delta; 704 cosy_delta = internal::gSinCosTbl[idxy].cos_delta; 705 706 siny = siny_val + ry * siny_delta; 707 cosy = cosy_val + ry * cosy_delta; 708 709 sinz_val = internal::gSinCosTbl[idxz].sin_val; 710 cosz_val = internal::gSinCosTbl[idxz].cos_val; 711 sinz_delta = internal::gSinCosTbl[idxz].sin_delta; 712 cosz_delta = internal::gSinCosTbl[idxz].cos_delta; 713 714 sinz = sinz_val + rz * sinz_delta; 715 cosz = cosz_val + rz * cosz_delta; 716 717 } 718 719 sinx = (negx) ? -sinx : sinx; 720 siny = (negy) ? -siny : siny; 721 sinz = (negz) ? -sinz : sinz; 722 723 } 724 725 f00 = cosz * cosy; 726 f10 = sinz * cosy; 727 f21 = sinx * cosy; 728 f22 = cosx * cosy; 729 730 f1 = cosx * sinz; 731 f2 = sinx * cosz; 732 733 f01 = f2 * siny - f1; 734 f12 = f1 * siny - f2; 735 736 f3 = sinx * sinz; 737 f4 = cosx * cosz; 738 739 f02 = f4 * siny + f3; 740 f11 = f3 * siny + f4; 741 742 pOut->f._00 = f00; 743 pOut->f._10 = f10; 744 pOut->f._21 = f21; 745 pOut->f._22 = f22; 746 747 pOut->f._01 = f01; 748 pOut->f._12 = f12; 749 pOut->f._02 = f02; 750 pOut->f._11 = f11; 751 pOut->f._20 = -siny; 752 753 *(unsigned int*)&pOut->f._03 = 0x00000000; 754 *(unsigned int*)&pOut->f._13 = 0x00000000; 755 *(unsigned int*)&pOut->f._23 = 0x00000000; 756 757 return pOut; 758} 759 760/*!--------------------------------------------------------------------------* 761 @brief 行列の逆行列を計算します。 762 763 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じ行列を指していても構いません。 764 @param[in] p 元となる行列へのポインタ。 765 766 @return 逆行列が存在すれば 1 を、存在しなければ 0 を返します。 767 *---------------------------------------------------------------------------*/ 768NN_MATH_INLINE u32 769MTX34InverseC(MTX34* pOut, const MTX34* p) 770{ 771 MTX34 mTmp; 772 f32 (*m)[4]; 773 f32 det; 774 775 NN_NULL_ASSERT( p ); 776 NN_NULL_ASSERT( pOut ); 777 778 f32 (*const inv)[4] = pOut->m; 779 const f32 (*const src)[4] = p->m; 780 781 if ( p == pOut ) 782 { 783 m = mTmp.m; 784 } 785 else 786 { 787 m = inv; 788 } 789 790 // compute the determinant of the upper 3x3 submatrix 791 det = src[0][0]*src[1][1]*src[2][2] + src[0][1]*src[1][2]*src[2][0] + src[0][2]*src[1][0]*src[2][1] 792 - src[2][0]*src[1][1]*src[0][2] - src[1][0]*src[0][1]*src[2][2] - src[0][0]*src[2][1]*src[1][2]; 793 794 // check if matrix is singular 795 if ( det == 0.0f ) 796 { 797 return 0; 798 } 799 800 // compute the inverse of the upper submatrix: 801 802 // find the transposed matrix of cofactors of the upper submatrix 803 // and multiply by (1/det) 804 805 det = 1.0f / det; 806 807 m[0][0] = (src[1][1]*src[2][2] - src[2][1]*src[1][2]) * det; 808 m[0][1] = -(src[0][1]*src[2][2] - src[2][1]*src[0][2]) * det; 809 m[0][2] = (src[0][1]*src[1][2] - src[1][1]*src[0][2]) * det; 810 811 m[1][0] = -(src[1][0]*src[2][2] - src[2][0]*src[1][2]) * det; 812 m[1][1] = (src[0][0]*src[2][2] - src[2][0]*src[0][2]) * det; 813 m[1][2] = -(src[0][0]*src[1][2] - src[1][0]*src[0][2]) * det; 814 815 m[2][0] = (src[1][0]*src[2][1] - src[2][0]*src[1][1]) * det; 816 m[2][1] = -(src[0][0]*src[2][1] - src[2][0]*src[0][1]) * det; 817 m[2][2] = (src[0][0]*src[1][1] - src[1][0]*src[0][1]) * det; 818 819 820 // compute (invA)*(-C) 821 m[0][3] = -m[0][0]*src[0][3] - m[0][1]*src[1][3] - m[0][2]*src[2][3]; 822 m[1][3] = -m[1][0]*src[0][3] - m[1][1]*src[1][3] - m[1][2]*src[2][3]; 823 m[2][3] = -m[2][0]*src[0][3] - m[2][1]*src[1][3] - m[2][2]*src[2][3]; 824 825 // copy back if needed 826 if ( m == mTmp.m ) 827 { 828 MTX34Copy( pOut, &mTmp ); 829 } 830 831 return 1; 832} 833 834 835/*!--------------------------------------------------------------------------* 836 @brief 行列の転置行列を作成します。 837 838 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じ行列を指していても構いません。 839 @param[in] p 転置する行列へのポインタ。 840 841 @return pOut を返します。 842 *---------------------------------------------------------------------------*/ 843NN_MATH_INLINE MTX34* 844MTX34TransposeC(MTX34* pOut, const MTX34* p) 845{ 846 MTX34 mTmp; 847 848 NN_NULL_ASSERT( p ); 849 NN_NULL_ASSERT( pOut ); 850 851 const f32 (*const src)[4] = p->m; 852 f32 (*m)[4]; 853 854 if (p == pOut) 855 { 856 m = mTmp.m; 857 } 858 else 859 { 860 m = pOut->m; 861 } 862 863 m[0][0] = src[0][0]; m[0][1] = src[1][0]; m[0][2] = src[2][0]; m[0][3] = 0.0f; 864 m[1][0] = src[0][1]; m[1][1] = src[1][1]; m[1][2] = src[2][1]; m[1][3] = 0.0f; 865 m[2][0] = src[0][2]; m[2][1] = src[1][2]; m[2][2] = src[2][2]; m[2][3] = 0.0f; 866 867 // copy back if needed 868 if ( m == mTmp.m ) 869 { 870 MTX34Copy( pOut, &mTmp ); 871 } 872 873 return pOut; 874} 875 876 877/*!--------------------------------------------------------------------------* 878 @brief 行列の逆転置行列を計算します。 879 880 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じ行列を指していても構いません。 881 @param[in] p 元となる行列へのポインタ。 882 883 @return 逆行列が存在すれば 1 を、存在しなければ 0 を返します。 884 *---------------------------------------------------------------------------*/ 885NN_MATH_INLINE u32 886MTX34InvTransposeC(MTX34* pOut, const MTX34* __restrict p) 887{ 888 MTX34 mTmp; 889 f32 (*m)[4]; 890 f32 det; 891 892 NN_NULL_ASSERT(p); 893 NN_NULL_ASSERT(pOut); 894 895 f32 (*const invX)[4] = pOut->m; 896 const f32 (*const src)[4] = p->m; 897 898 if ( p == pOut ) 899 { 900 m = mTmp.m; 901 } 902 else 903 { 904 m = invX; 905 } 906 907 // compute the determinant of the upper 3x3 submatrix 908 det = src[0][0]*src[1][1]*src[2][2] + src[0][1]*src[1][2]*src[2][0] + src[0][2]*src[1][0]*src[2][1] 909 - src[2][0]*src[1][1]*src[0][2] - src[1][0]*src[0][1]*src[2][2] - src[0][0]*src[2][1]*src[1][2]; 910 911 // check if matrix is singular 912 if ( det == 0.0f ) 913 { 914 return 0; 915 } 916 917 // compute the inverse-transpose of the upper submatrix: 918 919 // find the transposed matrix of cofactors of the upper submatrix 920 // and multiply by (1/det) 921 922 det = 1.0f / det; 923 924 m[0][0] = (src[1][1]*src[2][2] - src[2][1]*src[1][2]) * det; 925 m[0][1] = -(src[1][0]*src[2][2] - src[2][0]*src[1][2]) * det; 926 m[0][2] = (src[1][0]*src[2][1] - src[2][0]*src[1][1]) * det; 927 928 m[1][0] = -(src[0][1]*src[2][2] - src[2][1]*src[0][2]) * det; 929 m[1][1] = (src[0][0]*src[2][2] - src[2][0]*src[0][2]) * det; 930 m[1][2] = -(src[0][0]*src[2][1] - src[2][0]*src[0][1]) * det; 931 932 m[2][0] = (src[0][1]*src[1][2] - src[1][1]*src[0][2]) * det; 933 m[2][1] = -(src[0][0]*src[1][2] - src[1][0]*src[0][2]) * det; 934 m[2][2] = (src[0][0]*src[1][1] - src[1][0]*src[0][1]) * det; 935 936 937 // the fourth columns should be all zero 938 m[0][3] = 0.0F; 939 m[1][3] = 0.0F; 940 m[2][3] = 0.0F; 941 942 // copy back if needed 943 if ( m == mTmp.m ) 944 { 945 MTX34Copy( pOut, &mTmp ); 946 } 947 948 return 1; 949} 950 951 952/*!--------------------------------------------------------------------------* 953 @brief カメラ行列を設定します。 954 955 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 956 @param[in] pCamPos カメラの位置を指定するベクトルへのポインタ。 957 @param[in] pCamUp カメラの上方向を指定するベクトルへのポインタ。 958 @param[in] pTarget カメラの注視点を指定するベクトルへのポインタ。 959 960 @return pOut を返します。 961 *---------------------------------------------------------------------------*/ 962NN_MATH_INLINE MTX34* 963MTX34LookAtC(MTX34* pOut, const VEC3* pCamPos, const VEC3* pCamUp, const VEC3* pTarget) 964{ 965 NN_NULL_ASSERT(pOut); 966 NN_NULL_ASSERT(pCamPos); 967 NN_NULL_ASSERT(pCamUp); 968 NN_NULL_ASSERT(pTarget); 969 970 f32 (*const m)[4] = pOut->m; 971 972 // compute unit target vector 973 // use negative value to look down (-Z) axis 974 VEC3 vLook; 975 VEC3Sub(&vLook, pCamPos, pTarget); 976 VEC3Normalize(&vLook, &vLook); 977 978 // vRight = pCamUp x vLook 979 VEC3 vRight; 980 VEC3Cross(&vRight, pCamUp, &vLook); 981 VEC3Normalize(&vRight, &vRight); 982 983 // vUp = vLook x vRight 984 VEC3 vUp; 985 VEC3Cross(&vUp, &vLook, &vRight); 986 // Don't need to normalize vUp since it should already be unit length 987 // VECNormalize( &vUp, &vUp ); 988 989 m[0][0] = vRight.x; 990 m[0][1] = vRight.y; 991 m[0][2] = vRight.z; 992 m[0][3] = -( pCamPos->x * vRight.x + pCamPos->y * vRight.y + pCamPos->z * vRight.z ); 993 994 m[1][0] = vUp.x; 995 m[1][1] = vUp.y; 996 m[1][2] = vUp.z; 997 m[1][3] = -( pCamPos->x * vUp.x + pCamPos->y * vUp.y + pCamPos->z * vUp.z ); 998 999 m[2][0] = vLook.x; 1000 m[2][1] = vLook.y; 1001 m[2][2] = vLook.z; 1002 m[2][3] = -( pCamPos->x * vLook.x + pCamPos->y * vLook.y + pCamPos->z * vLook.z ); 1003 1004 return pOut; 1005} 1006NN_MATH_INLINE MTX34* 1007MTX34LookAtC_FAST(MTX34* pOut, const VEC3* pCamPos, const VEC3* pCamUp, const VEC3* pTarget) 1008{ 1009 NN_NULL_ASSERT(pOut); 1010 NN_NULL_ASSERT(pCamPos); 1011 NN_NULL_ASSERT(pCamUp); 1012 NN_NULL_ASSERT(pTarget); 1013 1014 f32 (*const m)[4] = pOut->m; 1015 1016 // compute unit target vector 1017 // use negative value to look down (-Z) axis 1018 f32 vLookx, vLooky, vLookz; 1019 { 1020 vLookx = pCamPos->x - pTarget->x; 1021 vLooky = pCamPos->y - pTarget->y; 1022 vLookz = pCamPos->z - pTarget->z; 1023 } 1024 1025 // vLook Normalize 1026 { 1027 f32 mag = (vLookx * vLookx) + (vLooky * vLooky) + (vLookz * vLookz); 1028 1029 NN_ASSERTMSG(mag != 0, "MATHNormalize3(): zero magnitude vector"); 1030 1031 mag = 1.0f / ::std::sqrtf(mag); 1032 1033 1034 vLookx = vLookx * mag; 1035 vLooky = vLooky * mag; 1036 vLookz = vLookz * mag; 1037 } 1038 1039 // vRight = pCamUp x vLook 1040 f32 vRightx, vRighty, vRightz; 1041 { 1042 vRightx = ( pCamUp->y * vLookz ) - ( pCamUp->z * vLooky ); 1043 vRighty = ( pCamUp->z * vLookx ) - ( pCamUp->x * vLookz ); 1044 vRightz = ( pCamUp->x * vLooky ) - ( pCamUp->y * vLookx ); 1045 } 1046 1047 // vRight Normalize 1048 { 1049 f32 mag = (vRightx * vRightx) + (vRighty * vRighty) + (vRightz * vRightz); 1050 1051 NN_ASSERTMSG(mag != 0, "MATHNormalize3(): zero magnitude vector"); 1052 1053 mag = 1.0f / ::std::sqrtf(mag); 1054 1055 vRightx = vRightx * mag; 1056 vRighty = vRighty * mag; 1057 vRightz = vRightz * mag; 1058 } 1059 1060 // vUp = vLook x vRight 1061 f32 vUpx, vUpy, vUpz; 1062 { 1063 vUpx = ( vLooky * vRightz ) - ( vLookz * vRighty ); 1064 vUpy = ( vLookz * vRightx ) - ( vLookx * vRightz ); 1065 vUpz = ( vLookx * vRighty ) - ( vLooky * vRightx ); 1066 } 1067 1068 1069 // Don't need to normalize vUp since it should already be unit length 1070 // VECNormalize( &vUp, &vUp ); 1071 f32 tmp1, tmp2, tmp3; 1072 1073 tmp1 = -( pCamPos->x * vRightx + pCamPos->y * vRighty + pCamPos->z * vRightz ); 1074 tmp2 = -( pCamPos->x * vUpx + pCamPos->y * vUpy + pCamPos->z * vUpz ); 1075 tmp3 = -( pCamPos->x * vLookx + pCamPos->y * vLooky + pCamPos->z * vLookz ); 1076 1077 m[0][0] = vRightx; 1078 m[0][1] = vRighty; 1079 m[0][2] = vRightz; 1080 1081 m[1][0] = vUpx; 1082 m[1][1] = vUpy; 1083 m[1][2] = vUpz; 1084 1085 m[2][0] = vLookx; 1086 m[2][1] = vLooky; 1087 m[2][2] = vLookz; 1088 1089 m[0][3] = tmp1; 1090 m[1][3] = tmp2; 1091 m[2][3] = tmp3; 1092 1093 return pOut; 1094} 1095 1096/*!--------------------------------------------------------------------------* 1097 @brief カメラ行列を設定します。 1098 1099 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 1100 @param[in] pCamPos カメラの位置を指定するベクトルへのポインタ。 1101 @param[in] twist カメラの視線方向に対する回転角度。単位は Degree です。 1102 @param[in] pTarget カメラの注視点を指定するベクトルへのポインタ。 1103 1104 @return pOut を返します。 1105 *---------------------------------------------------------------------------*/ 1106NN_MATH_INLINE MTX34* 1107MTX34LookAtC(MTX34* pOut, const VEC3* pCamPos, f32 twist, const VEC3* pTarget) 1108{ 1109 NN_NULL_ASSERT(pOut); 1110 NN_NULL_ASSERT(pCamPos); 1111 NN_NULL_ASSERT(pTarget); 1112 1113 f32 (*const m)[4] = pOut->m; 1114 1115 // カメラ座標系のZ方向 1116 VEC3 lookReverse(pCamPos->x - pTarget->x, pCamPos->y - pTarget->y, pCamPos->z - pTarget->z); 1117 1118 if ((lookReverse.x == 0.0f) && (lookReverse.z == 0.0f)) 1119 { 1120 // カメラとターゲットのXZ座標が同じ場合ツイストは定義されない 1121 m[0][0] = 1.0f; 1122 m[0][1] = 0.0f; 1123 m[0][2] = 0.0f; 1124 m[0][3] = -pCamPos->x; 1125 1126 m[1][0] = 0.0f; 1127 m[1][1] = 0.0f; 1128 1129 m[2][0] = 0.0f; 1130 m[2][2] = 0.0f; 1131 1132 if (lookReverse.y <= 0.0f) 1133 { 1134 // 真上を見るとき 1135 m[1][2] = 1.0f; 1136 m[1][3] = -pCamPos->z; 1137 1138 m[2][1] = -1.0f; 1139 m[2][3] = pCamPos->y; 1140 } 1141 else 1142 { 1143 // 真下を見るとき 1144 m[1][2] = -1.0f; 1145 m[1][3] = pCamPos->z; 1146 1147 m[2][1] = 1.0f; 1148 m[2][3] = -pCamPos->y; 1149 } 1150 } 1151 else 1152 { 1153 // カメラ座標系のX方向 1154 VEC3 r(lookReverse.z, 0.0f, -lookReverse.x); 1155 1156 VEC3Normalize(&lookReverse, &lookReverse); 1157 VEC3Normalize(&r, &r); 1158 1159 // カメラ座標系のY方向 1160 VEC3 u; 1161 VEC3Cross(&u, &lookReverse, &r); 1162 1163 f32 st, ct; 1164 SinCosDeg(&st, &ct, twist); 1165 VEC3 right, up; 1166 1167 // r軸, u軸をru平面上でcameraTwistだけ半時計回りに回転させてrightを求める 1168 // r.y == 0であることに注意 1169 right.x = st * u.x + ct * r.x; 1170 right.y = st * u.y; 1171 right.z = st * u.z + ct * r.z; 1172 1173 up.x = ct * u.x - st * r.x; 1174 up.y = ct * u.y; 1175 up.z = ct * u.z - st * r.z; 1176 1177 // right 1178 m[0][0] = right.x; 1179 m[0][1] = right.y; 1180 m[0][2] = right.z; 1181 m[0][3] = -VEC3Dot(pCamPos, &right); 1182 1183 // up 1184 m[1][0] = up.x; 1185 m[1][1] = up.y; 1186 m[1][2] = up.z; 1187 m[1][3] = -VEC3Dot(pCamPos, &up); 1188 1189 // look 1190 m[2][0] = lookReverse.x; 1191 m[2][1] = lookReverse.y; 1192 m[2][2] = lookReverse.z; 1193 m[2][3] = -VEC3Dot(pCamPos, &lookReverse); 1194 } 1195 1196 return pOut; 1197} 1198NN_MATH_INLINE MTX34* 1199MTX34LookAtC_FAST(MTX34* pOut, const VEC3* pCamPos, f32 twist, const VEC3* pTarget) 1200{ 1201 NN_NULL_ASSERT(pOut); 1202 NN_NULL_ASSERT(pCamPos); 1203 NN_NULL_ASSERT(pTarget); 1204 1205 f32 (*const m)[4] = pOut->m; 1206 1207 // カメラ座標系のZ方向 1208 f32 lookReversex, lookReversey, lookReversez; 1209 1210 lookReversex = pCamPos->x - pTarget->x; 1211 lookReversez = pCamPos->z - pTarget->z; 1212 lookReversey = pCamPos->y - pTarget->y; 1213 1214 if ((lookReversex == 0.0f) && (lookReversez == 0.0f)) 1215 { 1216 // カメラとターゲットのXZ座標が同じ場合ツイストは定義されない 1217 m[0][0] = 1.0f; 1218 m[0][1] = 0.0f; 1219 m[0][2] = 0.0f; 1220 m[0][3] = -pCamPos->x; 1221 1222 m[1][0] = 0.0f; 1223 m[1][1] = 0.0f; 1224 1225 m[2][0] = 0.0f; 1226 m[2][2] = 0.0f; 1227 1228 if (lookReversey <= 0.0f) 1229 { 1230 // 真上を見るとき 1231 m[1][2] = 1.0f; 1232 m[1][3] = -pCamPos->z; 1233 1234 m[2][1] = -1.0f; 1235 m[2][3] = pCamPos->y; 1236 } 1237 else 1238 { 1239 // 真下を見るとき 1240 m[1][2] = -1.0f; 1241 m[1][3] = pCamPos->z; 1242 1243 m[2][1] = 1.0f; 1244 m[2][3] = -pCamPos->y; 1245 } 1246 } 1247 else 1248 { 1249 // カメラ座標系のX方向 1250 f32 rx, ry, rz; 1251 f32 mag1, mag2; 1252 f32 ux, uy, uz; 1253 f32 fidx; 1254 1255 mag1 = (lookReversez * lookReversez) + (-lookReversex * -lookReversex); 1256 mag2 = (lookReversex * lookReversex) + (lookReversey * lookReversey) + (lookReversez * lookReversez); 1257 NN_ASSERTMSG(mag1 != 0, "MATHNormalize3(): zero magnitude vector"); 1258 NN_ASSERTMSG(mag2 != 0, "MATHNormalize3(): zero magnitude vector"); 1259 mag1 = ::std::sqrtf(mag1); 1260 mag2 = ::std::sqrtf(mag2); 1261 fidx = NN_MATH_DEG_TO_FIDX(twist); 1262 mag1 = 1.0f / mag1; 1263 mag2 = 1.0f / mag2; 1264 1265 // r Normalize 1266 { 1267 rx = lookReversez * mag1; 1268 ry = 0.0f; 1269 rz = -lookReversex * mag1; 1270 } 1271 // lookReverse Normalize 1272 { 1273 lookReversex = lookReversex * mag2; 1274 lookReversey = lookReversey * mag2; 1275 lookReversez = lookReversez * mag2; 1276 } 1277 1278 // カメラ座標系のY方向 1279 { 1280 ux = ( lookReversey * rz ) - ( lookReversez * ry ); 1281 uy = ( lookReversez * rx ) - ( lookReversex * rz ); 1282 uz = ( lookReversex * ry ) - ( lookReversey * rx ); 1283 } 1284 1285 1286 f32 st, ct; 1287// SinCosDeg(&st, &ct, twist); 1288 SinCosFIdx(&st, &ct, fidx); 1289 f32 rightx, righty, rightz; 1290 f32 upx, upy, upz; 1291 1292 // r軸, u軸をru平面上でcameraTwistだけ半時計回りに回転させてrightを求める 1293 // r.y == 0であることに注意 1294 rightx = st * ux + ct * rx; 1295 righty = st * uy; 1296 rightz = st * uz + ct * rz; 1297 1298 upx = ct * ux - st * rx; 1299 upy = ct * uy; 1300 upz = ct * uz - st * rz; 1301 1302 // right 1303 f32 tmp1, tmp2, tmp3; 1304 1305 tmp1 = pCamPos->x * rightx + pCamPos->y * righty + pCamPos->z * rightz; 1306 tmp2 = pCamPos->x * upx + pCamPos->y * upy + pCamPos->z * upz; 1307 tmp3 = pCamPos->x * lookReversex + pCamPos->y * lookReversey + pCamPos->z * lookReversez; 1308 1309 m[0][0] = rightx; 1310 m[0][1] = righty; 1311 m[0][2] = rightz; 1312 m[0][3] = -tmp1; 1313 1314 // up 1315 m[1][0] = upx; 1316 m[1][1] = upy; 1317 m[1][2] = upz; 1318 m[1][3] = -tmp2; 1319 1320 // look 1321 m[2][0] = lookReversex; 1322 m[2][1] = lookReversey; 1323 m[2][2] = lookReversez; 1324 m[2][3] = -tmp3; 1325 } 1326 1327 return pOut; 1328} 1329 1330/*!--------------------------------------------------------------------------* 1331 @brief カメラ行列を設定します。 1332 1333 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 1334 @param[in] pCamPos カメラの位置を指定するベクトルへのポインタ。 1335 @param[in] pCamRotate カメラの回転量を指定するベクトルへのポインタ。単位は Degree です。 1336 1337 @return pOut を返します。 1338 *---------------------------------------------------------------------------*/ 1339NN_MATH_INLINE MTX34* 1340MTX34CameraRotateC(MTX34* pOut, const VEC3* pCamPos, const VEC3* pCamRotate) 1341{ 1342 NN_NULL_ASSERT(pOut); 1343 NN_NULL_ASSERT(pCamPos); 1344 NN_NULL_ASSERT(pCamRotate); 1345 1346 f32 (*const m)[4] = pOut->m; 1347 1348 f32 sx, sy, sz, cx, cy, cz; 1349 SinCosDeg(&sx, &cx, pCamRotate->x); 1350 SinCosDeg(&sy, &cy, pCamRotate->y); 1351 SinCosDeg(&sz, &cz, pCamRotate->z); 1352 1353 // Z軸, X軸, Y軸の順番で回転させている 1354 VEC3 right, up, back; 1355 1356 right.x = sx * sy * sz + cy * cz; 1357 right.y = cx * sz; 1358 right.z = sx * cy * sz - sy * cz; 1359 1360 up.x = sx * sy * cz - cy * sz; 1361 up.y = cx * cz; 1362 up.z = sx * cy * cz + sy * sz; 1363 1364 back.x = cx * sy; 1365 back.y = - sx; 1366 back.z = cx * cy; 1367 1368 m[0][0] = right.x; 1369 m[0][1] = right.y; 1370 m[0][2] = right.z; 1371 m[0][3] = -VEC3Dot(pCamPos, &right); 1372 1373 m[1][0] = up.x; 1374 m[1][1] = up.y; 1375 m[1][2] = up.z; 1376 m[1][3] = -VEC3Dot(pCamPos, &up); 1377 1378 m[2][0] = back.x; 1379 m[2][1] = back.y; 1380 m[2][2] = back.z; 1381 m[2][3] = -VEC3Dot(pCamPos, &back); 1382 1383 return pOut; 1384} 1385NN_MATH_INLINE MTX34* 1386MTX34CameraRotateC_FAST(MTX34* pOut, const VEC3* pCamPos, const VEC3* pCamRotate) 1387{ 1388 NN_NULL_ASSERT(pOut); 1389 NN_NULL_ASSERT(pCamPos); 1390 NN_NULL_ASSERT(pCamRotate); 1391 1392 f32 (*const m)[4] = pOut->m; 1393 1394 f32 sinx, cosx; 1395 f32 siny, cosy; 1396 f32 sinz, cosz; 1397 f32 fIdxX = NN_MATH_DEG_TO_FIDX(pCamRotate->x); 1398 f32 fIdxY = NN_MATH_DEG_TO_FIDX(pCamRotate->y); 1399 f32 fIdxZ = NN_MATH_DEG_TO_FIDX(pCamRotate->z); 1400 1401 { 1402 1403 u16 idxx; 1404 f32 abs_fidxx; 1405 f32 rx; 1406 1407 u16 idxy; 1408 f32 abs_fidxy; 1409 f32 ry; 1410 1411 u16 idxz; 1412 f32 abs_fidxz; 1413 f32 rz; 1414 1415 int negx, negy, negz; 1416 1417 negx = (fIdxX < 0.0f) ? 1 : 0; 1418 abs_fidxx = FAbs(fIdxX); 1419 negy = (fIdxY < 0.0f) ? 1 : 0; 1420 abs_fidxy = FAbs(fIdxY); 1421 negz = (fIdxZ < 0.0f) ? 1 : 0; 1422 abs_fidxz = FAbs(fIdxZ); 1423 1424 1425 while ( abs_fidxx >= 65536.0f ) 1426 { 1427 abs_fidxx -= 65536.0f; 1428 } 1429 while ( abs_fidxy >= 65536.0f ) 1430 { 1431 abs_fidxy -= 65536.0f; 1432 } 1433 while ( abs_fidxz >= 65536.0f ) 1434 { 1435 abs_fidxz -= 65536.0f; 1436 } 1437 1438 idxx = F32ToU16(abs_fidxx); 1439 idxy = F32ToU16(abs_fidxy); 1440 idxz = F32ToU16(abs_fidxz); 1441 { 1442 f32 idxxf, idxyf, idxzf; 1443 1444 idxxf = U16ToF32(idxx); 1445 idxyf = U16ToF32(idxy); 1446 idxzf = U16ToF32(idxz); 1447 1448 rx = abs_fidxx - idxxf; 1449 ry = abs_fidxy - idxyf; 1450 rz = abs_fidxz - idxzf; 1451 1452 1453 } 1454 1455 idxx &= 0xff; 1456 idxy &= 0xff; 1457 idxz &= 0xff; 1458 1459 { 1460 f32 sinx_val, sinx_delta, cosx_val, cosx_delta; 1461 f32 siny_val, siny_delta, cosy_val, cosy_delta; 1462 f32 sinz_val, sinz_delta, cosz_val, cosz_delta; 1463 1464 sinx_val = internal::gSinCosTbl[idxx].sin_val; 1465 cosx_val = internal::gSinCosTbl[idxx].cos_val; 1466 sinx_delta = internal::gSinCosTbl[idxx].sin_delta; 1467 cosx_delta = internal::gSinCosTbl[idxx].cos_delta; 1468 1469 sinx = sinx_val + rx * sinx_delta; 1470 cosx = cosx_val + rx * cosx_delta; 1471 1472 siny_val = internal::gSinCosTbl[idxy].sin_val; 1473 cosy_val = internal::gSinCosTbl[idxy].cos_val; 1474 siny_delta = internal::gSinCosTbl[idxy].sin_delta; 1475 cosy_delta = internal::gSinCosTbl[idxy].cos_delta; 1476 1477 siny = siny_val + ry * siny_delta; 1478 cosy = cosy_val + ry * cosy_delta; 1479 1480 sinz_val = internal::gSinCosTbl[idxz].sin_val; 1481 cosz_val = internal::gSinCosTbl[idxz].cos_val; 1482 sinz_delta = internal::gSinCosTbl[idxz].sin_delta; 1483 cosz_delta = internal::gSinCosTbl[idxz].cos_delta; 1484 1485 sinz = sinz_val + rz * sinz_delta; 1486 cosz = cosz_val + rz * cosz_delta; 1487 1488 } 1489 1490 sinx = (negx) ? -sinx : sinx; 1491 siny = (negy) ? -siny : siny; 1492 sinz = (negz) ? -sinz : sinz; 1493 1494 } 1495 1496 1497 1498 1499 // Z軸, X軸, Y軸の順番で回転させている 1500 register VEC3 right, up, back; 1501 register f32 m00, m01, m02, m03; 1502 register f32 m10, m11, m12, m13; 1503 register f32 m20, m21, m22, m23; 1504 1505 1506 1507 right.x = sinx * siny * sinz + cosy * cosz; 1508 right.y = cosx * sinz; 1509 right.z = sinx * cosy * sinz - siny * cosz; 1510 1511 up.x = sinx * siny * cosz - cosy * sinz; 1512 up.y = cosx * cosz; 1513 up.z = sinx * cosy * cosz + siny * sinz; 1514 1515 back.x = cosx * siny; 1516 back.y = - sinx; 1517 back.z = cosx * cosy; 1518 1519 m00 = right.x; 1520 m01 = right.y; 1521 m02 = right.z; 1522 m03 = -VEC3Dot(pCamPos, &right); 1523 1524 m10 = up.x; 1525 m11 = up.y; 1526 m12 = up.z; 1527 m13 = -VEC3Dot(pCamPos, &up); 1528 1529 m20 = back.x; 1530 m21 = back.y; 1531 m22 = back.z; 1532 m23 = -VEC3Dot(pCamPos, &back); 1533 1534 m[0][0] = m00; 1535 m[0][1] = m01; 1536 m[0][2] = m02; 1537 m[0][3] = m03; 1538 1539 m[1][0] = m10; 1540 m[1][1] = m11; 1541 m[1][2] = m12; 1542 m[1][3] = m13; 1543 1544 m[2][0] = m20; 1545 m[2][1] = m21; 1546 m[2][2] = m22; 1547 m[2][3] = m23; 1548 1549 return pOut; 1550} 1551 1552/*! 1553 @} 1554*/ 1555/*! 1556 @name クォータニオン 1557 @{ 1558*/ 1559 1560/*!--------------------------------------------------------------------------* 1561 @brief クォータニオンから回転行列を作成します。 1562 1563 @param[out] pOut 計算結果を受け取るバッファへのポインタ。 1564 @param[in] pQ 元となるクォータニオンへのポインタ。 1565 1566 @return pOut を返します。 1567 *---------------------------------------------------------------------------*/ 1568NN_MATH_INLINE MTX34* 1569QUATToMTX34C(MTX34* pOut, const QUAT* pQ) 1570{ 1571 f32 s, xs, ys, zs; 1572 f32 wx, wy, wz, xx, xy, xz, yy, yz, zz; 1573 1574 NN_NULL_ASSERT(pOut); 1575 NN_NULL_ASSERT(pQ); 1576 NN_ASSERT( pQ->x || pQ->y || pQ->z || pQ->w ); 1577 1578 f32 (*const m)[4] = pOut->m; 1579 1580 s = 2.0f / ( (pQ->x * pQ->x) + (pQ->y * pQ->y) + (pQ->z * pQ->z) + (pQ->w * pQ->w) ); 1581 1582 xs = pQ->x * s; ys = pQ->y * s; zs = pQ->z * s; 1583 wx = pQ->w * xs; wy = pQ->w * ys; wz = pQ->w * zs; 1584 xx = pQ->x * xs; xy = pQ->x * ys; xz = pQ->x * zs; 1585 yy = pQ->y * ys; yz = pQ->y * zs; zz = pQ->z * zs; 1586 1587 m[0][0] = 1.0f - (yy + zz); 1588 m[0][1] = xy - wz; 1589 m[0][2] = xz + wy; 1590 m[0][3] = 0.0f; 1591 1592 m[1][0] = xy + wz; 1593 m[1][1] = 1.0f - (xx + zz); 1594 m[1][2] = yz - wx; 1595 m[1][3] = 0.0f; 1596 1597 m[2][0] = xz - wy; 1598 m[2][1] = yz + wx; 1599 m[2][2] = 1.0f - (xx + yy); 1600 m[2][3] = 0.0f; 1601 1602 return pOut; 1603} 1604NN_MATH_INLINE MTX34* 1605QUATToMTX34C_FAST(MTX34* pOut, const QUAT* pQ) 1606{ 1607 f32 s, xs, ys, zs; 1608 f32 wx, wy, wz, xx, xy, xz, yy, yz, zz; 1609 f32 m00, m01, m02, m10, m11, m12, m20, m21, m22; 1610 f32 pQx, pQy, pQz, pQw; 1611 1612 NN_NULL_ASSERT(pOut); 1613 NN_NULL_ASSERT(pQ); 1614 NN_ASSERT( pQ->x || pQ->y || pQ->z || pQ->w ); 1615 1616 f32 (*const m)[4] = pOut->m; 1617 1618 pQx = pQ->x; 1619 pQy = pQ->y; 1620 pQz = pQ->z; 1621 pQw = pQ->w; 1622 1623 s = 2.0f / ( (pQx * pQx) + (pQy * pQy) + (pQz * pQz) + (pQw * pQw) ); 1624 1625 xs = pQx * s; ys = pQy * s; zs = pQz * s; 1626 wx = pQw * xs; wy = pQw * ys; wz = pQw * zs; 1627 xx = pQx * xs; xy = pQx * ys; xz = pQx * zs; 1628 yy = pQy * ys; yz = pQy * zs; zz = pQz * zs; 1629 1630 m00 = 1.0f - (yy + zz); 1631 m01 = xy - wz; 1632 m02 = xz + wy; 1633 1634 m10 = xy + wz; 1635 m11 = 1.0f - (xx + zz); 1636 m12 = yz - wx; 1637 1638 m20 = xz - wy; 1639 m21 = yz + wx; 1640 m22 = 1.0f - (xx + yy); 1641 1642 m[0][3] = 0.0f; 1643 m[1][3] = 0.0f; 1644 m[2][3] = 0.0f; 1645 1646 m[0][0] = m00; 1647 m[0][1] = m01; 1648 m[0][2] = m02; 1649 1650 m[1][0] = m10; 1651 m[1][1] = m11; 1652 m[1][2] = m12; 1653 1654 m[2][0] = m20; 1655 m[2][1] = m21; 1656 m[2][2] = m22; 1657 1658 1659 return pOut; 1660} 1661 1662/*! 1663 @} 1664*/ 1665 1666} // namespace ARMv6 1667} // namespace math 1668} // namespace nn 1669