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: 24529 $
14 *---------------------------------------------------------------------------*/
15
16#include <cmath>
17#include <nn/math/math_Vector3.h>
18
19namespace nn {
20namespace math {
21
22/* ------------------------------------------------------------------------
23        MTX44
24   ------------------------------------------------------------------------ */
25
26/*!
27    @name    行列
28    @{
29*/
30
31/*!--------------------------------------------------------------------------*
32  @brief        零行列を作成します。
33
34  @param[out]   pOut  零行列を格納するバッファへのポインタ。
35
36  @return       pOut を返します。
37 *---------------------------------------------------------------------------*/
38NN_MATH_INLINE MTX44*
39MTX44Zero(MTX44* 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 =
44    pOut->f._30 = pOut->f._31 = pOut->f._32 = pOut->f._33 = 0.f;
45
46    return pOut;
47}
48
49
50/*!--------------------------------------------------------------------------*
51  @brief        単位行列を作成します。
52
53  @param[out]   pOut  単位行列を格納するバッファへのポインタ。
54
55  @return       pOut を返します。
56 *---------------------------------------------------------------------------*/
57NN_MATH_INLINE MTX44*
58MTX44Identity(MTX44* pOut)
59{
60    NN_NULL_ASSERT( pOut );
61
62    MTX44Copy(pOut, MTX44::Identity());
63
64    return pOut;
65}
66
67/*!--------------------------------------------------------------------------*
68  @brief        行列の差を計算します。
69
70  @param[out]   pOut  計算結果を受け取るバッファへのポインタ。p1, p2 と同じ行列を指していても構いません。
71  @param[in]    p1    左辺値へのポインタ。
72  @param[in]    p2    右辺値へのポインタ。
73
74  @return       pOut を返します。
75 *---------------------------------------------------------------------------*/
76NN_MATH_INLINE MTX44*
77MTX44Sub(MTX44* pOut, const MTX44* p1, const MTX44* p2)
78{
79    pOut->f._00 = p1->f._00 - p2->f._00;
80    pOut->f._01 = p1->f._01 - p2->f._01;
81    pOut->f._02 = p1->f._02 - p2->f._02;
82    pOut->f._03 = p1->f._03 - p2->f._03;
83
84    pOut->f._10 = p1->f._10 - p2->f._10;
85    pOut->f._11 = p1->f._11 - p2->f._11;
86    pOut->f._12 = p1->f._12 - p2->f._12;
87    pOut->f._13 = p1->f._13 - p2->f._13;
88
89    pOut->f._20 = p1->f._20 - p2->f._20;
90    pOut->f._21 = p1->f._21 - p2->f._21;
91    pOut->f._22 = p1->f._22 - p2->f._22;
92    pOut->f._23 = p1->f._23 - p2->f._23;
93
94    pOut->f._30 = p1->f._30 - p2->f._30;
95    pOut->f._31 = p1->f._31 - p2->f._31;
96    pOut->f._32 = p1->f._32 - p2->f._32;
97    pOut->f._33 = p1->f._33 - p2->f._33;
98
99    return pOut;
100}
101
102/*!--------------------------------------------------------------------------*
103  @brief        行列が単位行列かどうか判定します。
104
105  @param[in]    p  判定対象の行列へのポインタ。
106
107  @return       p が単位行列であれば true そうでなければ false を返します。
108 *---------------------------------------------------------------------------*/
109NN_MATH_INLINE bool
110MTX44IsIdentity(const MTX44* p)
111{
112    return p->f._00 == 1.f && p->f._01 == 0.f && p->f._02 == 0.f && p->f._03 == 0.f &&
113           p->f._10 == 0.f && p->f._11 == 1.f && p->f._12 == 0.f && p->f._13 == 0.f &&
114           p->f._20 == 0.f && p->f._21 == 0.f && p->f._22 == 1.f && p->f._23 == 0.f &&
115           p->f._30 == 0.f && p->f._31 == 0.f && p->f._32 == 0.f && p->f._33 == 1.f;
116}
117#if 0
118namespace {
119    /*---------------------------------------------------------------------------*
120          Description:  画面方向に向けて射影行列を回転します。
121
122      Arguments:    pOut    回転をおこなう行列へのポインタ
123                    pivot
124
125      Returns:
126     *---------------------------------------------------------------------------*/
127    inline MTX44*
128    MTX44Pivot( MTX44* pOut, PivotDirection pivot )
129    {
130        // TODO: 処理の最適化が必要。
131
132        const f32 PIVOT_ROTATION_SIN_COS[ PIVOT_NUM ][ 2 ] =
133        {
134        #ifdef NN_PLATFORM_CTR
135            { 0.0f,  1.0f }, // NONE
136            { -1.0f, 0.0f }, // TO_UP
137            { 0.0f, -1.0f }, // TO_RIGHT
138            { 1.0f,  0.0f }, // TO_BOTTOM
139            { 0.0f,  1.0f }, // TO_LEFT
140        #else
141            { 0.0f,  1.0f }, // NONE
142            { 0.0f,  1.0f }, // TO_UP
143            { -1.0f, 0.0f }, // TO_RIGHT
144            { 0.0f, -1.0f }, // TO_BOTTOM
145            { 1.0f,  0.0f }, // TO_LEFT
146        #endif
147        };
148
149        if ( pivot == PIVOT_NONE )
150        {
151            return pOut;
152        }
153
154        f32 sin = PIVOT_ROTATION_SIN_COS[ pivot ][ 0 ];
155        f32 cos = PIVOT_ROTATION_SIN_COS[ pivot ][ 1 ];
156
157        f32 (*const m)[4] = pOut->m;
158
159        if ( sin == 0.0f )
160        {
161            m[0][0] = cos * m[0][0];
162            m[0][1] = cos * m[0][1];
163            m[0][2] = cos * m[0][2];
164            m[0][3] = cos * m[0][3];
165
166            m[1][0] = cos * m[1][0];
167            m[1][1] = cos * m[1][1];
168            m[1][2] = cos * m[1][2];
169            m[1][3] = cos * m[1][3];
170        }
171        else // if ( cos == 0.0f )
172        {
173            f32 tmp = m[0][0];
174            m[0][0] = -sin * m[1][0];
175            m[1][0] = sin * tmp;
176
177            tmp = m[0][1];
178            m[0][1] = -sin * m[1][1];
179            m[1][1] = sin * tmp;
180
181            tmp = m[0][2];
182            m[0][2] = -sin * m[1][2];
183            m[1][2] = sin * tmp;
184
185            tmp = m[0][3];
186            m[0][3] = -sin * m[1][3];
187            m[1][3] = sin * tmp;
188        }
189
190        return pOut;
191    }
192
193} // namespace
194#endif
195
196/*!--------------------------------------------------------------------------*
197  @brief        画面の回転を掛けた射影行列を作成します。
198                射影行列をニアクリッピング面での視錐台を元に作成します。
199
200  @param[out]   pOut  射影行列を格納する行列へのポインタ。
201  @param[in]    l     ニアクリッピング面での視錐台左辺の X 座標
202  @param[in]    r     ニアクリッピング面での視錐台右辺の X 座標
203  @param[in]    b     ニアクリッピング面での視錐台下辺の Y 座標
204  @param[in]    t     ニアクリッピング面での視錐台上辺の Y 座標
205  @param[in]    n     ニアクリッピング面までの距離。
206  @param[in]    f     ファークリッピング面までの距離。
207  @param[in]    pivot 画面の回転方向
208
209  @return       pOut を返します。
210 *---------------------------------------------------------------------------*/
211NN_MATH_INLINE MTX44*
212MTX44FrustumPivot(MTX44* pOut, f32 l, f32 r, f32 b, f32 t, f32 n, f32 f, PivotDirection pivot)
213{
214    MTX44Frustum( pOut, l, r, b, t, n, f );
215    MTX44Pivot( pOut, pivot );
216
217    return pOut;
218}
219
220/*!--------------------------------------------------------------------------*
221  @brief        画面の回転を掛けた射影行列を作成します。
222                正射影行列を作成します。
223
224  @param[out]   pOut  射影行列を格納する行列へのポインタ。
225  @param[in]    l     ニアクリッピング面での視錐台左辺の X 座標
226  @param[in]    r     ニアクリッピング面での視錐台右辺の X 座標
227  @param[in]    b     ニアクリッピング面での視錐台下辺の Y 座標
228  @param[in]    t     ニアクリッピング面での視錐台上辺の Y 座標
229  @param[in]    n     ニアクリッピング面までの距離。
230  @param[in]    f     ファークリッピング面までの距離。
231  @param[in]    pivot 画面の回転方向
232
233  @return       pOut を返します。
234 *---------------------------------------------------------------------------*/
235NN_MATH_INLINE MTX44*
236MTX44OrthoPivot(MTX44* pOut, f32 l, f32 r, f32 b, f32 t, f32 n, f32 f, PivotDirection pivot)
237{
238    MTX44Ortho( pOut, l, r, b, t, n, f );
239    MTX44Pivot( pOut, pivot );
240
241    return pOut;
242}
243
244/*!--------------------------------------------------------------------------*
245  @brief        画面の回転を掛けた射影行列を作成します。
246                射影行列を視野角とアスペクト比から作成します。
247
248  @param[out]   pOut    射影行列を格納する行列へのポインタ。
249  @param[in]    fovy    縦方向の視野角(Radian)
250  @param[in]    aspect  視野のアスペクト比(幅/高さ)
251  @param[in]    n       ニアクリッピング面までの距離。
252  @param[in]    f       ファークリッピング面までの距離。
253  @param[in]    pivot   画面の回転方向
254
255  @return       pOut を返します。
256 *---------------------------------------------------------------------------*/
257NN_MATH_INLINE MTX44*
258MTX44PerspectivePivotRad(MTX44* pOut, f32 fovy, f32 aspect, f32 n, f32 f, PivotDirection pivot)
259{
260    MTX44PerspectiveRad( pOut, fovy, aspect, n, f );
261    MTX44Pivot( pOut, pivot );
262
263    return pOut;
264}
265
266
267
268
269
270/*!--------------------------------------------------------------------------*
271  @brief        行列の配列に左から行列を掛けます。
272
273  @param[out]   pOut   計算結果を受け取る配列の先頭へのポインタ。
274  @param[in]    p1     左辺値となる行列へのポインタ。
275  @param[in]    pSrc   右辺値となる行列の配列の先頭へのポインタ
276  @param[in]    count  右辺値なる行列の配列の要素数
277
278  @return       pOut を返します。
279 *---------------------------------------------------------------------------*/
280NN_MATH_INLINE MTX44*
281MTX44MultArray(MTX44* pOut, const MTX44* __restrict p1, const MTX44* __restrict pSrc, s32 count)
282{
283    MTX44* pOutBase = pOut;
284
285    NN_NULL_ASSERT( pOut );
286    NN_NULL_ASSERT( p1 );
287    NN_NULL_ASSERT( pSrc );
288    NN_ASSERT( count > 1 );
289
290    for ( s32 i = 0 ; i < count ; i++ )
291    {
292        MTX44Mult(pOut, p1, pSrc);
293
294        pSrc++;
295        pOut++;
296    }
297
298    return pOutBase;
299}
300
301namespace {
302    inline void SwapF(f32 &a, f32 &b)
303    {
304        f32 tmp;
305        tmp = a;
306        a = b;
307        b = tmp;
308    }
309} // namespace (unnamed)
310
311
312/*!--------------------------------------------------------------------------*
313  @brief        指定する軸の周りを回転させる回転行列を作成します。
314
315  @param[out]   pOut   計算結果を受け取るバッファへのポインタ。
316  @param[in]    pAxis  回転軸を指定するベクトルへのポインタ。
317  @param[in]    fIdx   1 円周を 256.0 とする単位での回転量
318
319  @return       pOut を返します。
320 *---------------------------------------------------------------------------*/
321NN_MATH_INLINE MTX44*
322MTX44RotAxisFIdx(MTX44* pOut, const VEC3* pAxis, f32 fIdx)
323{
324    // とりあえずは遅くてもいい
325    MTX44RotAxisRad_(pOut, pAxis, NN_MATH_FIDX_TO_RAD(fIdx));
326
327    return pOut;
328}
329
330
331
332/*!
333    @}
334*/
335
336}  // namespace math
337}  // namespace nn
338