1/*---------------------------------------------------------------------------*
2  Project:  Horizon
3  File:     math_Matrix23.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
16namespace nn {
17namespace math {
18
19/* ------------------------------------------------------------------------
20        MTX23
21   ------------------------------------------------------------------------ */
22
23/*!
24    @name    行列
25    @{
26*/
27
28/*!--------------------------------------------------------------------------*
29  @brief        2x3行列をコピーします。
30
31  @param[out]   pOut    コピー先の行列のポインタです。
32  @param[in]    p       コピー元の行列のポインタです。
33
34  @return       pOut を返します。
35 *---------------------------------------------------------------------------*/
36NN_MATH_INLINE MTX23*
37MTX23Copy(MTX23* pOut, const MTX23* p)
38{
39    NN_NULL_ASSERT( pOut );
40    NN_NULL_ASSERT( p );
41
42    if (pOut != p)
43    {
44        *pOut = *p;
45    }
46
47    return pOut;
48}
49
50/*!--------------------------------------------------------------------------*
51  @brief        ゼロ行列を作成します。
52
53  @param[out]   pOut    ゼロ行列を格納するバッファへのポインタです。
54
55  @return       pOut を返します。
56 *---------------------------------------------------------------------------*/
57NN_MATH_INLINE MTX23*
58MTX23Zero(MTX23* pOut)
59{
60    NN_NULL_ASSERT( pOut );
61
62    pOut->f._00 = pOut->f._01 = pOut->f._02 =
63    pOut->f._10 = pOut->f._11 = pOut->f._12 = 0.f;
64
65    return pOut;
66}
67
68/*!--------------------------------------------------------------------------*
69  @brief        2x3の単位行列を作成します。
70
71  @param[out]   pOut    単位行列を格納するバッファへのポインタです。
72
73  @return       pOut を返します。
74 *---------------------------------------------------------------------------*/
75NN_MATH_INLINE MTX23*
76MTX23Identity(MTX23* pOut)
77{
78    NN_NULL_ASSERT( pOut );
79
80    MTX23Copy(pOut, MTX23::Identity());
81
82    return pOut;
83}
84
85/*!--------------------------------------------------------------------------*
86  @brief        単位行列であるかどうかを判定します。
87
88  @param[in]    p    判定対象の行列です。
89
90  @return       p が単位行列であれば、true を返します。
91 *---------------------------------------------------------------------------*/
92NN_MATH_INLINE bool
93MTX23IsIdentity(const MTX23* p)
94{
95    NN_NULL_ASSERT( p );
96
97    return p->f._00 == 1.f && p->f._01 == 0.f && p->f._02 == 0.f &&
98           p->f._10 == 0.f && p->f._11 == 1.f && p->f._12 == 0.f;
99}
100
101/*!--------------------------------------------------------------------------*
102  @brief        2x3 行列を加算します。
103
104  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。p1, p2 と同じ行列を指しても構いません。
105  @param[in]    p1      元の行列へのポインタです。
106  @param[in]    p2      足す行列へのポインタです。
107
108  @return       pOut を返します。
109 *---------------------------------------------------------------------------*/
110NN_MATH_INLINE MTX23*
111MTX23Add(MTX23* pOut, const MTX23* p1, const MTX23* p2)
112{
113    NN_NULL_ASSERT( pOut );
114    NN_NULL_ASSERT( p1 );
115    NN_NULL_ASSERT( p2 );
116
117    pOut->f._00 = p1->f._00 + p2->f._00;
118    pOut->f._01 = p1->f._01 + p2->f._01;
119    pOut->f._02 = p1->f._02 + p2->f._02;
120
121    pOut->f._10 = p1->f._10 + p2->f._10;
122    pOut->f._11 = p1->f._11 + p2->f._11;
123    pOut->f._12 = p1->f._12 + p2->f._12;
124
125    return pOut;
126}
127
128/*!--------------------------------------------------------------------------*
129  @brief        2x3 行列の減算です。
130
131  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。p1, p2 と同じ行列を指しても構いません。
132  @param[in]    p1      元の行列へのポインタです。
133  @param[in]    p2      減算する行列へのポインタです。
134
135  @return
136 *---------------------------------------------------------------------------*/
137NN_MATH_INLINE MTX23*
138MTX23Sub(MTX23* pOut, const MTX23* p1, const MTX23* p2)
139{
140    NN_NULL_ASSERT( pOut );
141    NN_NULL_ASSERT( p1 );
142    NN_NULL_ASSERT( p2 );
143
144    pOut->f._00 = p1->f._00 - p2->f._00;
145    pOut->f._01 = p1->f._01 - p2->f._01;
146    pOut->f._02 = p1->f._02 - p2->f._02;
147
148    pOut->f._10 = p1->f._10 - p2->f._10;
149    pOut->f._11 = p1->f._11 - p2->f._11;
150    pOut->f._12 = p1->f._12 - p2->f._12;
151
152    return pOut;
153}
154
155/*!--------------------------------------------------------------------------*
156  @brief        2x3行列のスカラー積を計算します。
157
158  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。p と同じ行列を指していても構いません。
159  @param[in]    p       元の行列へのポインタです。
160  @param[in]    f       掛ける数です。
161
162  @return       pOut を返します。
163 *---------------------------------------------------------------------------*/
164NN_MATH_INLINE MTX23*
165MTX23Mult(MTX23* pOut, const MTX23* p, f32 f)
166{
167    NN_NULL_ASSERT( pOut );
168    NN_NULL_ASSERT( p );
169
170    pOut->f._00 = p->f._00 * f;
171    pOut->f._01 = p->f._01 * f;
172    pOut->f._02 = p->f._02 * f;
173
174    pOut->f._10 = p->f._10 * f;
175    pOut->f._11 = p->f._11 * f;
176    pOut->f._12 = p->f._12 * f;
177
178    return pOut;
179}
180
181/*!--------------------------------------------------------------------------*
182  @brief        2x3 行列の積を計算します。
183
184  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。 p1, p2 と同じ行列を指していても構いません。
185  @param[in]    p1      左辺値へのポインタです。
186  @param[in]    p2      右辺値へのポインタです。
187
188  @return       pOut を返します。
189 *---------------------------------------------------------------------------*/
190NN_MATH_INLINE MTX23*
191MTX23Mult(MTX23* pOut, const MTX23* __restrict p1, const MTX23* __restrict p2)
192{
193    NN_NULL_ASSERT( pOut );
194    NN_NULL_ASSERT( p1 );
195    NN_NULL_ASSERT( p2 );
196
197    MTX23  tmp;
198    MTX23* __restrict pMtx;
199
200    if ( (pOut == p1) || (pOut == p2) )
201    {
202        pMtx = &tmp;
203    }
204    else
205    {
206        pMtx = pOut;
207    }
208
209    pMtx->f._00 = p1->f._00 * p2->f._00 + p1->f._01 * p2->f._10;
210    pMtx->f._01 = p1->f._00 * p2->f._01 + p1->f._01 * p2->f._11;
211    pMtx->f._02 = p1->f._00 * p2->f._02 + p1->f._01 * p2->f._12 + p1->f._02;
212
213    pMtx->f._10 = p1->f._10 * p2->f._00 + p1->f._11 * p2->f._10;
214    pMtx->f._11 = p1->f._10 * p2->f._01 + p1->f._11 * p2->f._11;
215    pMtx->f._12 = p1->f._10 * p2->f._02 + p1->f._11 * p2->f._12 + p1->f._12;
216
217    if (pMtx == &tmp)
218    {
219        MTX23Copy(pOut, &tmp);
220    }
221
222    return pOut;
223}
224
225
226/*!--------------------------------------------------------------------------*
227  @brief        2x3 行列にスケール変換を適用します。
228
229  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。pMと同じ行列を指していても構いません。
230  @param[in]    pM      元となる行列へのポインタです。
231  @param[in]    pS      それぞれの軸方向のスケール値が格納されたベクトルのポインタです。
232
233  @return       pOut を返します。
234 *---------------------------------------------------------------------------*/
235NN_MATH_INLINE MTX23*
236MTX23Scale(MTX23* pOut, const MTX23* __restrict pM, const VEC2* __restrict pS)
237{
238    NN_NULL_ASSERT( pOut );
239    NN_NULL_ASSERT( pM );
240    NN_NULL_ASSERT( pS );
241
242    pOut->f._00 = pM->f._00 * pS->x;
243    pOut->f._10 = pM->f._10 * pS->x;
244
245    pOut->f._01 = pM->f._01 * pS->y;
246    pOut->f._11 = pM->f._11 * pS->y;
247
248    if (pOut != pM)
249    {
250        pOut->f._02 = pM->f._02;
251        pOut->f._12 = pM->f._12;
252    }
253    return pOut;
254}
255
256/*!--------------------------------------------------------------------------*
257  @brief        2x3 行列に平行移動を適用します。移動行列を右から掛けます。
258
259  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。pMと同じ行列を指していても構いません。
260  @param[in]    pM      元となる行列へのポインタです。
261  @param[in]    pT      それぞれの軸方向の移動量が格納されたベクトルのポインタです。
262
263  @return       pOUt を返します。
264 *---------------------------------------------------------------------------*/
265NN_MATH_INLINE MTX23*
266MTX23Translate(MTX23* pOut, const MTX23* pM, const VEC2* pT)
267{
268    if (pOut != pM)
269    {
270        (void)MTX23Copy(pOut, pM);
271    }
272
273    VEC2 tmp;
274    VEC2Transform(&tmp, pM, pT);
275
276    pOut->f._02 = tmp.x;
277    pOut->f._12 = tmp.y;
278    return pOut;
279}
280
281/*!--------------------------------------------------------------------------*
282  @brief        回転行列を作成します。
283
284  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。
285  @param[in]    fIdx    1円周を 256.0 とする単位での角度です。
286
287  @return       pOut を返します。
288 *---------------------------------------------------------------------------*/
289NN_MATH_INLINE MTX23*
290MTX23RotFIdx(MTX23* pOut, f32 fIdx)
291{
292    NN_NULL_ASSERT( pOut );
293
294    f32 sin, cos;
295
296    SinCosFIdx(&sin, &cos, fIdx);
297
298    pOut->f._00 = pOut->f._11 = cos;
299    pOut->f._01 = sin;
300    pOut->f._10 = -sin;
301    pOut->f._02 = pOut->f._12 = 0.f;
302
303    return pOut;
304}
305
306
307/*!--------------------------------------------------------------------------*
308  @brief        回転の中心を指定した回転行列を作成します。
309
310  @param[out]   pOut    計算結果を受け取るバッファへのポインタです。
311  @param[in]    pCenter 回転の中心座標です。
312  @param[in]    fIdx    1円周を 256.0 とする単位での角度です。
313
314  @return       pOut を返します。
315 *---------------------------------------------------------------------------*/
316NN_MATH_INLINE MTX23*
317MTX23RotCenterFIdx(MTX23* pOut, const VEC2* pCenter, f32 fIdx)
318{
319    NN_NULL_ASSERT( pOut );
320    NN_NULL_ASSERT( pCenter );
321
322    MTX23 trans;
323    trans.f._00 = trans.f._11 = 1.f;
324    trans.f._10 = trans.f._01 = 0.f;
325    trans.f._02 = pCenter->x;
326    trans.f._12 = pCenter->y;
327
328    f32 sin, cos;
329
330    SinCosFIdx(&sin, &cos, fIdx);
331
332    (void)MTX23RotFIdx(pOut, fIdx);
333
334    MTX23Mult(pOut, &trans, pOut);
335
336    trans.f._02 = -trans.f._02;
337    trans.f._12 = -trans.f._12;
338
339    MTX23Mult(pOut, pOut, &trans);
340
341    return pOut;
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
354 *---------------------------------------------------------------------------*/
355NN_MATH_INLINE MTX23*
356MTX23MAdd(MTX23* pOut, f32 t, const MTX23* p1, const MTX23* p2)
357{
358    NN_NULL_ASSERT( pOut );
359    NN_NULL_ASSERT( p1 );
360    NN_NULL_ASSERT( p2 );
361
362    pOut->f._00 = t * p1->f._00 + p2->f._00;
363    pOut->f._01 = t * p1->f._01 + p2->f._01;
364    pOut->f._02 = t * p1->f._02 + p2->f._02;
365
366    pOut->f._10 = t * p1->f._10 + p2->f._10;
367    pOut->f._11 = t * p1->f._11 + p2->f._11;
368    pOut->f._12 = t * p1->f._12 + p2->f._12;
369
370    return pOut;
371}
372
373/*!--------------------------------------------------------------------------*
374  @brief        2x2 行列を 2x3行列にコピーします。
375
376  @param[out]   pOut    コピー先の行列へのポインタです。
377  @param[in]    pM      コピー元の行列へのポインタです。
378
379  @return       pOut を返します。
380 *---------------------------------------------------------------------------*/
381NN_MATH_INLINE MTX23*
382MTX22ToMTX23(MTX23* pOut, const MTX22* pM)
383{
384    NN_NULL_ASSERT( pOut );
385    NN_NULL_ASSERT( pM );
386
387    pOut->f._00 = pM->f._00;
388    pOut->f._01 = pM->f._01;
389    pOut->f._10 = pM->f._10;
390    pOut->f._11 = pM->f._11;
391
392    pOut->f._02 = pOut->f._12 = 0.f;
393    return pOut;
394}
395
396/*!
397    @}
398*/
399
400}  // namespace math
401}  // namespace nn
402