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: 24035 $
14 *---------------------------------------------------------------------------*/
15#include <cmath>
16#include <nn/math/math_Vector3.h>
17
18namespace nn {
19namespace math {
20
21
22/* ------------------------------------------------------------------------
23        MTX34
24   ------------------------------------------------------------------------ */
25
26/*!
27    @name    行列
28    @{
29*/
30
31/*!--------------------------------------------------------------------------*
32  @brief        零行列を作成します。
33
34  @param[out]   pOut  零行列を格納するバッファへのポインタ。
35
36  @return       pOut を返します。
37 *---------------------------------------------------------------------------*/
38NN_MATH_INLINE MTX34*
39MTX34Zero(MTX34* pOut)
40{
41    pOut->f._00 = pOut->f._01 = pOut->f._02 = pOut->f._03 =
42    pOut->f._10 = pOut->f._11 = pOut->f._12 = pOut->f._13 =
43    pOut->f._20 = pOut->f._21 = pOut->f._22 = pOut->f._23 = 0.f;
44
45    return pOut;
46}
47
48/*!--------------------------------------------------------------------------*
49  @brief        単位行列を作成します。
50
51  @param[out]   pOut  単位行列を格納するバッファへのポインタ。
52
53  @return       pOut を返します。
54 *---------------------------------------------------------------------------*/
55NN_MATH_INLINE MTX34*
56MTX34Identity(MTX34* pOut)
57{
58    NN_NULL_ASSERT( pOut );
59
60    MTX34Copy(pOut, MTX34::Identity());
61
62    return pOut;
63}
64
65
66/*!--------------------------------------------------------------------------*
67  @brief        行列が単位行列かどうか判定します。
68
69  @param[in]    p  判定対象の行列へのポインタ。
70
71  @return       p が単位行列であれば true そうでなければ false を返します。
72 *---------------------------------------------------------------------------*/
73NN_MATH_INLINE bool
74MTX34IsIdentity(const MTX34* p)
75{
76    return p->f._00 == 1.f && p->f._01 == 0.f && p->f._02 == 0.f && p->f._03 == 0.f &&
77           p->f._10 == 0.f && p->f._11 == 1.f && p->f._12 == 0.f && p->f._13 == 0.f &&
78           p->f._20 == 0.f && p->f._21 == 0.f && p->f._22 == 1.f && p->f._23 == 0.f;
79}
80
81/*!--------------------------------------------------------------------------*
82  @brief        行列の差を計算します。
83
84  @param[out]   pOut  計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。
85  @param[in]    p1    左辺値へのポインタ。
86  @param[in]    p2    右辺値へのポインタ。
87
88  @return       pOut を返します。
89 *---------------------------------------------------------------------------*/
90NN_MATH_INLINE MTX34*
91MTX34Sub(MTX34* pOut, const MTX34* p1, const MTX34* p2)
92{
93    pOut->f._00 = p1->f._00 - p2->f._00;
94    pOut->f._01 = p1->f._01 - p2->f._01;
95    pOut->f._02 = p1->f._02 - p2->f._02;
96    pOut->f._03 = p1->f._03 - p2->f._03;
97
98    pOut->f._10 = p1->f._10 - p2->f._10;
99    pOut->f._11 = p1->f._11 - p2->f._11;
100    pOut->f._12 = p1->f._12 - p2->f._12;
101    pOut->f._13 = p1->f._13 - p2->f._13;
102
103    pOut->f._20 = p1->f._20 - p2->f._20;
104    pOut->f._21 = p1->f._21 - p2->f._21;
105    pOut->f._22 = p1->f._22 - p2->f._22;
106    pOut->f._23 = p1->f._23 - p2->f._23;
107
108    return pOut;
109}
110
111
112/*!--------------------------------------------------------------------------*
113  @brief        指定する軸の周りを回転させる回転行列を作成します。
114
115  @param[out]   pOut   計算結果を受け取るバッファへのポインタ。
116  @param[in]    pAxis  回転軸を指定するベクトルへのポインタ。
117  @param[in]    fIdx   1 円周を 256.0 とする単位での回転量
118
119  @return       pOut を返します。
120 *---------------------------------------------------------------------------*/
121NN_MATH_INLINE MTX34*
122MTX34RotAxisFIdx(MTX34* pOut, const VEC3* pAxis, f32 fIdx)
123{
124    // とりあえずは遅くてもいい
125    MTX34RotAxisRad_(pOut, pAxis, NN_MATH_FIDX_TO_RAD(fIdx));
126
127    return pOut;
128}
129
130
131/*!--------------------------------------------------------------------------*
132  @brief        回転行列に平行移動行列を左から掛けた行列を作成します。
133
134  @param[out]   pOut   計算結果を受け取るバッファへのポインタ。
135  @param[in]    fIdxX  1 円周を 256.0 とする単位での X 軸周りの角度
136  @param[in]    fIdxY  1 円周を 256.0 とする単位での Y 軸周りの角度
137  @param[in]    fIdxZ  1 円周を 256.0 とする単位での Z 軸周りの角度
138  @param[in]    pT     それぞれの軸方向の移動量が格納されたベクトルへのポインタ。
139
140  @return       pOut を返します。
141 *---------------------------------------------------------------------------*/
142NN_MATH_INLINE MTX34*
143MTX34RotXYZTranslateFIdx(MTX34* pOut, f32 fIdxX, f32 fIdxY, f32 fIdxZ, const VEC3* pT)
144{
145    (void)MTX34RotXYZFIdx(pOut, fIdxX, fIdxY, fIdxZ);
146    pOut->f._03 = pT->x;
147    pOut->f._13 = pT->y;
148    pOut->f._23 = pT->z;
149    return pOut;
150}
151
152/*!--------------------------------------------------------------------------*
153  @brief        3x4行列の逆転置行列を計算して3x3行列に格納します。
154
155  @param[out]   pOut  計算結果を受け取るバッファへのポインタ。
156  @param[in]    p     元となる行列へのポインタ。
157
158  @return       逆行列が存在すれば 1 を、存在しなければ 0 を返します。
159 *---------------------------------------------------------------------------*/
160NN_MATH_INLINE u32
161MTX34InvTranspose(MTX33* pOut, const MTX34* __restrict p)
162{
163    MTX34 tmp;
164    u32 rval = MTX34InvTranspose(&tmp, p);
165    (void)MTX34ToMTX33(pOut, &tmp);
166    return rval;
167}
168
169
170/*!--------------------------------------------------------------------------*
171  @brief        行列の配列に左から行列を掛けます。
172
173  @param[out]   pOut   計算結果を受け取る配列の先頭へのポインタ。
174  @param[in]    p1     左辺値となる行列へのポインタ。
175  @param[in]    pSrc   右辺値となる行列の配列の先頭へのポインタ
176  @param[in]    count  右辺値なる行列の配列の要素数
177
178  @return       pOut を返します。
179 *---------------------------------------------------------------------------*/
180NN_MATH_INLINE MTX34*
181MTX34MultArray(MTX34* pOut, const MTX34* __restrict p1, const MTX34* __restrict pSrc, s32 count)
182{
183    MTX34* pOutBase = pOut;
184
185    NN_NULL_ASSERT( pOut );
186    NN_NULL_ASSERT( p1 );
187    NN_NULL_ASSERT( pSrc );
188    NN_ASSERT( count > 1 );
189
190    for ( s32 i = 0 ; i < count ; i++ )
191    {
192        MTX34Mult(pOut, p1, pSrc);
193
194        pSrc++;
195        pOut++;
196    }
197
198    return pOutBase;
199}
200
201/*!--------------------------------------------------------------------------*
202  @brief        テクスチャマトリクス用射影行列を視錐体を元に作成します。
203
204  @param[out]   pOut        計算結果を受け取るバッファへのポインタです。
205  @param[in]    l           ニアクリップの左辺です。
206  @param[in]    r           ニアクリップの右辺です。
207  @param[in]    b           ニアクリップの下辺です。
208  @param[in]    t           ニアクリップの上辺です。
209  @param[in]    n           カメラからニアクリップまでの距離です。
210  @param[in]    scaleS      S軸方向のスケール値です。
211  @param[in]    scaleT      T軸方向のスケール値です。
212  @param[in]    translateS  S軸方向の移動値です。
213  @param[in]    translateT  T軸方向の移動値です。
214
215  @return       pOut を返します。
216 *---------------------------------------------------------------------------*/
217NN_MATH_INLINE MTX34*
218MTX34TextureProjectionFrustum(MTX34* pOut, f32 l, f32 r, f32 b, f32 t, f32 n, f32 scaleS, f32 scaleT, f32 translateS, f32 translateT)
219{
220    NN_ASSERT(t != b);
221    NN_ASSERT(l != r);
222    NN_NULL_ASSERT(pOut);
223
224    f32 reverseWidth = 1.0f / (r - l);
225
226    f32 (*const mtx)[4] = pOut->m;
227
228    mtx[0][0] = ((2.0f * n) * reverseWidth) * scaleS;
229    mtx[0][1] = 0.0f;
230    mtx[0][2] = (((r + l) * reverseWidth) * scaleS) - translateS;
231    mtx[0][3] = 0.0f;
232
233    f32 reverseHeight = 1.0f / (t - b);
234    mtx[1][0] = 0.0f;
235    mtx[1][1] = ((2.0f * n) * reverseHeight) * scaleT;
236    mtx[1][2] = (((t+ b) * reverseHeight) * scaleT) - translateT;
237    mtx[1][3] = 0.0f;
238
239    mtx[2][0] = 0.0f;
240    mtx[2][1] = 0.0f;
241    mtx[2][2] = -1.0f;
242    mtx[2][3] = 0.0f;
243    return pOut;
244}
245
246/*!--------------------------------------------------------------------------*
247  @brief        テクスチャマトリクス用射影行列を作成します。
248
249  @param[out]   pOut        計算結果を受け取るバッファへのポインタです。
250  @param[in]    fovy        垂直視野角です。単位はラジアンです。
251  @param[in]    aspect      クリップ面のアスペクト比です。
252  @param[in]    scaleS      S軸方向のスケール値です。
253  @param[in]    scaleT      T軸方向のスケール値です。
254  @param[in]    translateS  S軸方向の移動値です。
255  @param[in]    translateT  T軸方向の移動値です。
256
257  @return       pOut を返します。
258 *---------------------------------------------------------------------------*/
259NN_MATH_INLINE MTX34*
260MTX34TextureProjectionPerspective(MTX34* pOut, f32 fovy, f32 aspect, f32 scaleS, f32 scaleT, f32 translateS, f32 translateT)
261{
262    NN_ASSERT((fovy > 0.0f) && (fovy < math::F_PI));
263    NN_ASSERT(aspect != 0.0f);
264    NN_NULL_ASSERT(pOut);
265
266    float angle = fovy * 0.5f;
267    float cot = 1.0f / math::TanRad(angle);
268
269    f32 (*const mtx)[4] = pOut->m;
270
271    mtx[0][0] = (cot / aspect) * scaleS;
272    mtx[0][1] = 0.0f;
273    mtx[0][2] = -translateS;
274    mtx[0][3] = 0.0f;
275
276    mtx[1][0] = 0.0f;
277    mtx[1][1] = cot * scaleT;
278    mtx[1][2] = -translateT;
279    mtx[1][3] = 0.0f;
280
281    mtx[2][0] = 0.0f;
282    mtx[2][1] = 0.0f;
283    mtx[2][2] = -1.0f;
284    mtx[2][3] = 0.0f;
285
286    return pOut;
287}
288
289/*!--------------------------------------------------------------------------*
290  @brief        テクスチャマトリクス用平行射影行列を作成します。
291
292  @param[out]   pOut        計算結果を受け取るバッファへのポインタです。
293  @param[in]    l           ニアクリップの左辺です。
294  @param[in]    r           ニアクリップの右辺です。
295  @param[in]    b           ニアクリップの下辺です。
296  @param[in]    t           ニアクリップの上辺です。
297  @param[in]    scaleS      S軸方向のスケール値です。
298  @param[in]    scaleT      T軸方向のスケール値です。
299  @param[in]    translateS  S軸方向の移動値です。
300  @param[in]    translateT  T軸方向の移動値です。
301
302  @return       pOut を返します。
303 *---------------------------------------------------------------------------*/
304NN_MATH_INLINE MTX34*
305MTX34TextureProjectionOrtho(MTX34* pOut, f32 l, f32 r, f32 b, f32 t, f32 scaleS, f32 scaleT, f32 translateS, f32 translateT)
306{
307    NN_ASSERT(t != b);
308    NN_ASSERT(l != r);
309    NN_NULL_ASSERT(pOut);
310
311    float reverseWidth = 1.0f / (r - l);
312
313    f32 (*const mtx)[4] = pOut->m;
314
315    mtx[0][0] = 2.0f * reverseWidth * scaleS;
316    mtx[0][1] = 0.0f;
317    mtx[0][2] = 0.0f;
318    mtx[0][3] = ((-(r + l) * reverseWidth) * scaleS) + translateS;
319
320    float reverseHeight = 1.0f / (t - b);
321    mtx[1][0] = 0.0f;
322    mtx[1][1] = (2.0f * reverseHeight) * scaleT;
323    mtx[1][2] = 0.0f;
324    mtx[1][3] = ((-(t + b) * reverseHeight) * scaleT) + translateT;
325
326    mtx[2][0] = 0.0f;
327    mtx[2][1] = 0.0f;
328    mtx[2][2] = 0.0f;
329    mtx[2][3] = 1.0f;
330    return pOut;
331}
332
333/*!
334    @}
335*/
336
337
338}  // namespace math
339}  // namespace nn
340