1/*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: math_Matrix33.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#include <nn/math/math_Vector3.h> 16 17namespace nn { 18namespace math { 19namespace ARMv6 { 20 21#include <nn/hw/ARM/code32.h> 22/*! 23 @name 行列 24 @{ 25*/ 26 27template<typename TMatrix> 28inline asm TMatrix* 29MTX33MultAsm_ORG(TMatrix*, const TMatrix*, const TMatrix*) 30{ 31 VPUSH {d8-d13} // レジスタの保存 32 33 //templateの為、いちおう行列のあるオフセット値を計算する... 34 MOV r3,#__cpp(offsetof(TMatrix,f)) 35 ADD r1,r1,r3 36 ADD r2,r2,r3 37 MOV r3,#__cpp(TMatrix::COLUMN_COUNT)*4 38 39 VLDMIA r2,{s9-s11} // レジスタ[S9-S11]に行列p2の1行目 40 VLDMIA r1,{s0-s2} // レジスタ[S0-S2]に行列p1の1行目 41 ADD r1,r1,r3 42 ADD r2,r2,r3 43 VLDMIA r2,{s12-s14} // レジスタ[S12-S14]に行列p2の2行目 44 VLDMIA r1,{s3-s5} // レジスタ[S3-S5]に行列p1の2行目 45 ADD r1,r1,r3 46 ADD r2,r2,r3 47 VLDMIA r2,{s15-s17} // レジスタ[S15-S17]に行列p2の3行目 48 VLDMIA r1,{s6-s8} // レジスタ[S6-S8]に行列p1の3行目 49 50 VMUL.F32 s18,s9,s0 51 VMUL.F32 s19,s10,s0 52 VMUL.F32 s20,s11,s0 53 54 VMUL.F32 s21,s9,s3 55 VMUL.F32 s22,s10,s3 56 VMUL.F32 s23,s11,s3 57 58 VMUL.F32 s24,s9,s6 59 VMUL.F32 s25,s10,s6 60 VMUL.F32 s26,s11,s6 61 62 VMLA.F32 s18,s12,s1 63 VMLA.F32 s19,s13,s1 64 VMLA.F32 s20,s14,s1 65 66 VMLA.F32 s21,s12,s4 67 VMLA.F32 s22,s13,s4 68 VMLA.F32 s23,s14,s4 69 70 VMLA.F32 s24,s12,s7 71 VMLA.F32 s25,s13,s7 72 VMLA.F32 s26,s14,s7 73 74 VMLA.F32 s18,s15,s2 75 VMLA.F32 s19,s16,s2 76 VMLA.F32 s20,s17,s2 77 78 VMLA.F32 s21,s15,s5 79 VMLA.F32 s22,s16,s5 80 VMLA.F32 s23,s17,s5 81 82 VMLA.F32 s24,s15,s8 83 VMLA.F32 s25,s16,s8 84 VMLA.F32 s26,s17,s8 85 86 VSTMIA r0,{s18-s20} // 結果をストア 87 VPOP {d8-d9} // 分割POPした方が速い 88 ADD r1,r0,r3 89 VSTMIA r1,{s21-s23} // 結果をストア 90 VPOP {d10-d11} // 細切れにした方が速い 91 ADD r1,r1,r3 92 VSTMIA r1,{s24-s26} // 結果をストア 93 VPOP {d12-d13} // ブツ切りした方が速い 94 BX lr // 戻る 95} 96 97template<typename TMatrix> 98inline asm TMatrix* 99MTX33MultAsm(TMatrix*, const TMatrix*, const TMatrix*) 100{ 101 102 103 //templateの為、いちおう行列のあるオフセット値を計算する... 104 MOV r3,#__cpp(offsetof(TMatrix,f)) 105 ADD r1,r1,r3 106 ADD r2,r2,r3 107 MOV r3,#__cpp(TMatrix::COLUMN_COUNT)*4 108 109 CMP r3,#3*4 110 BNE LABELX 111 112 VPUSH {d8} // レジスタの保存 113 VLDMIA r2!,{s10-s15} // レジスタ[ S10-S15]に行列p2の1,2行目 114 115 VLDR.F32 s16,[r1,#3*4*0+4*0] // 行列p1[0][0] 116 VLDR.F32 s17,[r1,#3*4*1+4*0] // 行列p1[1][0] 117 118 VMUL.F32 s0,s10,s16 119 VMUL.F32 s1,s11,s16 120 VMUL.F32 s2,s12,s16 121 VLDR.F32 s16,[r1,#3*4*2+4*0] // 行列p1[2][0] 122 123 VMUL.F32 s3,s10,s17 124 VMUL.F32 s4,s11,s17 125 VMUL.F32 s5,s12,s17 126 VLDR.F32 s17,[r1,#3*4*0+4*1] // 行列p1[0][1] 127 128 VMUL.F32 s6,s10,s16 129 VMUL.F32 s7,s11,s16 130 VMUL.F32 s8,s12,s16 131 VLDR.F32 s16,[r1,#3*4*1+4*1] // 行列p1[1][1] 132 133 VLDMIA r2,{s10-s12} // レジスタ[ S10-S12]に行列p2の3行目 134 VMLA.F32 s0,s13,s17 135 VMLA.F32 s1,s14,s17 136 VMLA.F32 s2,s15,s17 137 VLDR.F32 s17,[r1,#3*4*2+4*1] // 行列p1[2][1] 138 139 VMLA.F32 s3,s13,s16 140 VMLA.F32 s4,s14,s16 141 VMLA.F32 s5,s15,s16 142 VLDR.F32 s16,[r1,#3*4*0+4*2] // 行列p1[0][2] 143 144 VMLA.F32 s6,s13,s17 145 VMLA.F32 s7,s14,s17 146 VMLA.F32 s8,s15,s17 147 VLDR.F32 s17,[r1,#3*4*1+4*2] // 行列p1[1][2] 148 149 VMLA.F32 s0,s10,s16 150 VMLA.F32 s1,s11,s16 151 VMLA.F32 s2,s12,s16 152 VLDR.F32 s16,[r1,#3*4*2+4*2] // 行列p1[2][2] 153 154 VMLA.F32 s3,s10,s17 155 VMLA.F32 s4,s11,s17 156 VMLA.F32 s5,s12,s17 157 158 VMLA.F32 s6,s10,s16 159 VMLA.F32 s7,s11,s16 160 VMLA.F32 s8,s12,s16 161 162 VPOP {d8} // POP 163 164 VSTMIA r0,{s0-s8} // 結果をストア 165 BX lr // 戻る 166 167LABELX 168 VPUSH {d8-d13} // レジスタの保存 169 VLDMIA r2,{s9-s11} // レジスタ[ S9-S11]に行列p2の1行目 170 VLDMIA r1,{s18-s20} // レジスタ[S18-S20]に行列p1の1行目 171 ADD r1,r1,r3 172 ADD r2,r2,r3 173 VLDMIA r2,{s12-s14} // レジスタ[S12-S14]に行列p2の2行目 174 VLDMIA r1,{s21-s23} // レジスタ[S21-S23]に行列p1の2行目 175 ADD r1,r1,r3 176 ADD r2,r2,r3 177 VLDMIA r2,{s15-s17} // レジスタ[S15-S17]に行列p2の3行目 178 VLDMIA r1,{s24-s26} // レジスタ[S24-S26]に行列p1の3行目 179 180 VMUL.F32 s0,s9,s18 181 VMUL.F32 s1,s10,s18 182 VMUL.F32 s2,s11,s18 183 184 VMUL.F32 s3,s9,s21 185 VMUL.F32 s4,s10,s21 186 VMUL.F32 s5,s11,s21 187 188 VMUL.F32 s6,s9,s24 189 VMUL.F32 s7,s10,s24 190 VMUL.F32 s8,s11,s24 191 192 VMLA.F32 s0,s12,s19 193 VMLA.F32 s1,s13,s19 194 VMLA.F32 s2,s14,s19 195 196 VMLA.F32 s3,s12,s22 197 VMLA.F32 s4,s13,s22 198 VMLA.F32 s5,s14,s22 199 200 VMLA.F32 s6,s12,s25 201 VMLA.F32 s7,s13,s25 202 VMLA.F32 s8,s14,s25 203 204 VMLA.F32 s0,s15,s20 205 VMLA.F32 s1,s16,s20 206 VMLA.F32 s2,s17,s20 207 208 VMLA.F32 s3,s15,s23 209 VMLA.F32 s4,s16,s23 210 VMLA.F32 s5,s17,s23 211 212 VMLA.F32 s6,s15,s26 213 VMLA.F32 s7,s16,s26 214 VMLA.F32 s8,s17,s26 215 216 VPOP {d8-d13} // POP 217 218 ADD r1,r0,r3 219 ADD r2,r1,r3 220 VSTMIA r0,{s0-s2} // 結果をストア 221 VSTMIA r1,{s3-s5} // 結果をストア 222 VSTMIA r2,{s6-s8} // 結果をストア 223 BX lr // 戻る 224 225} 226 227/*! 228 @} 229*/ 230 231#include <nn/hw/ARM/codereset.h> 232/*! 233 @name ユーティリティ 234 @{ 235*/ 236 237/*!--------------------------------------------------------------------------* 238 @brief ベクトルを行列で変換します。 239 240 @param[out] pOut 計算結果を受け取るバッファへのポインタ。pV と同じベクトルを指していても構いません。 241 @param[in] pM 変換行列へのポインタ。 242 @param[in] pV 元となるベクトルへのポインタ。 243 244 @return pOut を返します。 245 *---------------------------------------------------------------------------*/ 246NN_MATH_INLINE VEC3* 247VEC3TransformC(VEC3* pOut, const MTX33* pM, const VEC3* pV) 248{ 249 NN_NULL_ASSERT(pOut); 250 NN_NULL_ASSERT(pM); 251 NN_NULL_ASSERT(pV); 252 253 VEC3 vTmp; 254 VEC3* pDst = (pOut == pV) ? &vTmp : pOut; 255 pDst->x = pM->f._00 * pV->x + pM->f._01 * pV->y + pM->f._02 * pV->z; 256 pDst->y = pM->f._10 * pV->x + pM->f._11 * pV->y + pM->f._12 * pV->z; 257 pDst->z = pM->f._20 * pV->x + pM->f._21 * pV->y + pM->f._22 * pV->z; 258 259 if (pDst == &vTmp) 260 { 261 pOut->x = pDst->x; 262 pOut->y = pDst->y; 263 pOut->z = pDst->z; 264 } 265 266 return pOut; 267} 268 269/*! 270 @} 271*/ 272 273/* ------------------------------------------------------------------------ 274 MTX33 275 ------------------------------------------------------------------------ */ 276 277/*! 278 @name 行列 279 @{ 280*/ 281 282/*!--------------------------------------------------------------------------* 283 @brief 3x3行列の積を計算します。 284 285 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。 286 @param[in] p1 左の行列へのポインタ。 287 @param[in] p2 右の行列へのポインタ。 288 289 @return pOutを返します。 290 *---------------------------------------------------------------------------*/ 291template<typename TMatrix> 292inline TMatrix* 293MTX33MultC(TMatrix* pOut, const TMatrix* __restrict p1, const TMatrix* __restrict p2) 294{ 295 NN_NULL_ASSERT( p1 ); 296 NN_NULL_ASSERT( p2 ); 297 NN_NULL_ASSERT( pOut ); 298 299 TMatrix mTmp; 300 TMatrix* __restrict pDst = (pOut == p1 || pOut == p2) ? &mTmp : pOut; 301 302 pDst->f._00 = p1->f._00 * p2->f._00 + p1->f._01 * p2->f._10 + p1->f._02 * p2->f._20; 303 pDst->f._01 = p1->f._00 * p2->f._01 + p1->f._01 * p2->f._11 + p1->f._02 * p2->f._21; 304 pDst->f._02 = p1->f._00 * p2->f._02 + p1->f._01 * p2->f._12 + p1->f._02 * p2->f._22; 305 306 pDst->f._10 = p1->f._10 * p2->f._00 + p1->f._11 * p2->f._10 + p1->f._12 * p2->f._20; 307 pDst->f._11 = p1->f._10 * p2->f._01 + p1->f._11 * p2->f._11 + p1->f._12 * p2->f._21; 308 pDst->f._12 = p1->f._10 * p2->f._02 + p1->f._11 * p2->f._12 + p1->f._12 * p2->f._22; 309 310 pDst->f._20 = p1->f._20 * p2->f._00 + p1->f._21 * p2->f._10 + p1->f._22 * p2->f._20; 311 pDst->f._21 = p1->f._20 * p2->f._01 + p1->f._21 * p2->f._11 + p1->f._22 * p2->f._21; 312 pDst->f._22 = p1->f._20 * p2->f._02 + p1->f._21 * p2->f._12 + p1->f._22 * p2->f._22; 313 314 if (pDst == &mTmp) 315 { 316 pOut->f._00 = pDst->f._00; pOut->f._01 = pDst->f._01; pOut->f._02 = pDst->f._02; 317 pOut->f._10 = pDst->f._10; pOut->f._11 = pDst->f._11; pOut->f._12 = pDst->f._12; 318 pOut->f._20 = pDst->f._20; pOut->f._21 = pDst->f._21; pOut->f._22 = pDst->f._22; 319 } 320 321 return pOut; 322} 323 324/*!--------------------------------------------------------------------------* 325 @brief 3x3行列をコピーします。 326 327 @param[out] pOut コピー先の行列のポインタ 328 @param[in] p コピー元の行列のポインタ 329 330 @return pOutを返します。 331 *---------------------------------------------------------------------------*/ 332NN_MATH_INLINE MTX33* 333MTX33CopyC(MTX33* pOut, const MTX33* p) 334{ 335 if (pOut != p) 336 { 337 *pOut = *p; 338 } 339 340 return pOut; 341} 342 343 344 345/*!--------------------------------------------------------------------------* 346 @brief 行列を実数倍して、別の行列を足します。 347 348 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。 349 @param[in] t 掛ける数。 350 @param[in] p1 元の行列へのポインタ。 351 @param[in] p2 足す行列へのポインタ。 352 353 @return pOut を返します。 354 *---------------------------------------------------------------------------*/ 355NN_MATH_INLINE MTX33* 356MTX33MAddC(MTX33* pOut, f32 t, const MTX33* p1, const MTX33* p2) 357{ 358 pOut->f._00 = t * p1->f._00 + p2->f._00; 359 pOut->f._01 = t * p1->f._01 + p2->f._01; 360 pOut->f._02 = t * p1->f._02 + p2->f._02; 361 362 pOut->f._10 = t * p1->f._10 + p2->f._10; 363 pOut->f._11 = t * p1->f._11 + p2->f._11; 364 pOut->f._12 = t * p1->f._12 + p2->f._12; 365 366 pOut->f._20 = t * p1->f._20 + p2->f._20; 367 pOut->f._21 = t * p1->f._21 + p2->f._21; 368 pOut->f._22 = t * p1->f._22 + p2->f._22; 369 370 return pOut; 371} 372NN_MATH_INLINE MTX33* 373MTX33MAddC_FAST(MTX33* pOut, f32 t, const MTX33* p1, const MTX33* p2) 374{ 375 register f32 m00, m01, m02, m10, m11, m12, m20, m21, m22; 376 377 m00 = p2->f._00; 378 m01 = p2->f._01; 379 m02 = p2->f._02; 380 381 m10 = p2->f._10; 382 m11 = p2->f._11; 383 m12 = p2->f._12; 384 385 m20 = p2->f._20; 386 m21 = p2->f._21; 387 m22 = p2->f._22; 388 389 m00 += t * p1->f._00; 390 m01 += t * p1->f._01; 391 m02 += t * p1->f._02; 392 393 m10 += t * p1->f._10; 394 m11 += t * p1->f._11; 395 m12 += t * p1->f._12; 396 397 m20 += t * p1->f._20; 398 m21 += t * p1->f._21; 399 m22 += t * p1->f._22; 400 401 pOut->f._00 = m00; 402 pOut->f._01 = m01; 403 pOut->f._02 = m02; 404 405 pOut->f._10 = m10; 406 pOut->f._11 = m11; 407 pOut->f._12 = m12; 408 409 pOut->f._20 = m20; 410 pOut->f._21 = m21; 411 pOut->f._22 = m22; 412 413 return pOut; 414 415} 416 417/*! 418 @} 419*/ 420} // namespace ARMv6 421} // namespace math 422} // namespace nn 423