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: 45840 $
14 *---------------------------------------------------------------------------*/
15
16namespace nn {
17namespace math {
18
19/* ------------------------------------------------------------------------
20        MTX23
21   ------------------------------------------------------------------------ */
22NN_MATH_INLINE MTX23*
23MTX23Add(MTX23* pOut, const MTX23* p1, const MTX23* p2)
24{
25    NN_NULL_ASSERT( pOut );
26    NN_NULL_ASSERT( p1 );
27    NN_NULL_ASSERT( p2 );
28
29    pOut->f._00 = p1->f._00 + p2->f._00;
30    pOut->f._01 = p1->f._01 + p2->f._01;
31    pOut->f._02 = p1->f._02 + p2->f._02;
32
33    pOut->f._10 = p1->f._10 + p2->f._10;
34    pOut->f._11 = p1->f._11 + p2->f._11;
35    pOut->f._12 = p1->f._12 + p2->f._12;
36
37    return pOut;
38}
39
40NN_MATH_INLINE MTX23*
41MTX23Copy(MTX23* pOut, const MTX23* p)
42{
43    NN_NULL_ASSERT( pOut );
44    NN_NULL_ASSERT( p );
45
46    if (pOut != p)
47    {
48        *pOut = *p;
49    }
50
51    return pOut;
52}
53
54NN_MATH_INLINE MTX23*
55MTX23Identity(MTX23* pOut)
56{
57    NN_NULL_ASSERT( pOut );
58
59    MTX23Copy(pOut, MTX23::Identity());
60
61    return pOut;
62}
63
64NN_MATH_INLINE bool
65MTX23IsIdentity(const MTX23* p)
66{
67    NN_NULL_ASSERT( p );
68
69    return p->f._00 == 1.f && p->f._01 == 0.f && p->f._02 == 0.f &&
70           p->f._10 == 0.f && p->f._11 == 1.f && p->f._12 == 0.f;
71}
72
73NN_MATH_INLINE MTX23*
74MTX23MAdd(MTX23* pOut, f32 t, const MTX23* p1, const MTX23* p2)
75{
76    NN_NULL_ASSERT( pOut );
77    NN_NULL_ASSERT( p1 );
78    NN_NULL_ASSERT( p2 );
79
80    pOut->f._00 = t * p1->f._00 + p2->f._00;
81    pOut->f._01 = t * p1->f._01 + p2->f._01;
82    pOut->f._02 = t * p1->f._02 + p2->f._02;
83
84    pOut->f._10 = t * p1->f._10 + p2->f._10;
85    pOut->f._11 = t * p1->f._11 + p2->f._11;
86    pOut->f._12 = t * p1->f._12 + p2->f._12;
87
88    return pOut;
89}
90
91NN_MATH_INLINE MTX23*
92MTX23Mult(MTX23* pOut, const MTX23* p, f32 f)
93{
94    NN_NULL_ASSERT( pOut );
95    NN_NULL_ASSERT( p );
96
97    pOut->f._00 = p->f._00 * f;
98    pOut->f._01 = p->f._01 * f;
99    pOut->f._02 = p->f._02 * f;
100
101    pOut->f._10 = p->f._10 * f;
102    pOut->f._11 = p->f._11 * f;
103    pOut->f._12 = p->f._12 * f;
104
105    return pOut;
106}
107
108NN_MATH_INLINE MTX23*
109MTX23Mult(MTX23* pOut, const MTX23* __restrict p1, const MTX23* __restrict p2)
110{
111    NN_NULL_ASSERT( pOut );
112    NN_NULL_ASSERT( p1 );
113    NN_NULL_ASSERT( p2 );
114
115    MTX23  tmp;
116    MTX23* __restrict pMtx;
117
118    if ( (pOut == p1) || (pOut == p2) )
119    {
120        pMtx = &tmp;
121    }
122    else
123    {
124        pMtx = pOut;
125    }
126
127    pMtx->f._00 = p1->f._00 * p2->f._00 + p1->f._01 * p2->f._10;
128    pMtx->f._01 = p1->f._00 * p2->f._01 + p1->f._01 * p2->f._11;
129    pMtx->f._02 = p1->f._00 * p2->f._02 + p1->f._01 * p2->f._12 + p1->f._02;
130
131    pMtx->f._10 = p1->f._10 * p2->f._00 + p1->f._11 * p2->f._10;
132    pMtx->f._11 = p1->f._10 * p2->f._01 + p1->f._11 * p2->f._11;
133    pMtx->f._12 = p1->f._10 * p2->f._02 + p1->f._11 * p2->f._12 + p1->f._12;
134
135    if (pMtx == &tmp)
136    {
137        MTX23Copy(pOut, &tmp);
138    }
139
140    return pOut;
141}
142
143NN_MATH_INLINE MTX23*
144MTX23MultTranslate(MTX23* pOut, const MTX23* pM, const VEC2* pT)
145{
146    if (pOut != pM)
147    {
148        (void)MTX23Copy(pOut, pM);
149    }
150
151    VEC2 tmp;
152    VEC2Transform(&tmp, pM, pT);
153
154    pOut->f._02 = tmp.x;
155    pOut->f._12 = tmp.y;
156    return pOut;
157}
158
159NN_MATH_INLINE MTX23*
160MTX23MultTranslate(MTX23* pOut, const VEC2* pT, const MTX23* pM)
161{
162    NN_NULL_ASSERT(pOut);
163    NN_NULL_ASSERT(pT);
164    NN_NULL_ASSERT(pM);
165
166    const f32 (*const src)[3] = pM->m;
167    f32 (*const dst)[3] = pOut->m;
168
169    if ( src != dst )
170    {
171        dst[0][0] = src[0][0];    dst[0][1] = src[0][1];
172        dst[1][0] = src[1][0];    dst[1][1] = src[1][1];
173    }
174
175    dst[0][2] = src[0][2] + pT->x;
176    dst[1][2] = src[1][2] + pT->y;
177
178    return pOut;
179}
180
181NN_MATH_INLINE MTX23*
182MTX23RotCenterFIdx(MTX23* pOut, const VEC2* pCenter, f32 fIdx)
183{
184    NN_NULL_ASSERT( pOut );
185    NN_NULL_ASSERT( pCenter );
186
187    MTX23 trans;
188    trans.f._00 = trans.f._11 = 1.f;
189    trans.f._10 = trans.f._01 = 0.f;
190    trans.f._02 = pCenter->x;
191    trans.f._12 = pCenter->y;
192
193    f32 sin, cos;
194
195    SinCosFIdx(&sin, &cos, fIdx);
196
197    (void)MTX23RotFIdx(pOut, fIdx);
198
199    MTX23Mult(pOut, &trans, pOut);
200
201    trans.f._02 = -trans.f._02;
202    trans.f._12 = -trans.f._12;
203
204    MTX23Mult(pOut, pOut, &trans);
205
206    return pOut;
207}
208
209NN_MATH_INLINE MTX23*
210MTX23RotFIdx(MTX23* pOut, f32 fIdx)
211{
212    NN_NULL_ASSERT( pOut );
213
214    f32 sin, cos;
215
216    SinCosFIdx(&sin, &cos, fIdx);
217
218    pOut->f._00 = pOut->f._11 = cos;
219    pOut->f._01 = sin;
220    pOut->f._10 = -sin;
221    pOut->f._02 = pOut->f._12 = 0.f;
222
223    return pOut;
224}
225
226NN_MATH_INLINE MTX23*
227MTX23Scale(MTX23* pOut, const MTX23* __restrict pM, const VEC2* __restrict pS)
228{
229    NN_NULL_ASSERT( pOut );
230    NN_NULL_ASSERT( pM );
231    NN_NULL_ASSERT( pS );
232
233    pOut->f._00 = pM->f._00 * pS->x;
234    pOut->f._10 = pM->f._10 * pS->x;
235
236    pOut->f._01 = pM->f._01 * pS->y;
237    pOut->f._11 = pM->f._11 * pS->y;
238
239    if (pOut != pM)
240    {
241        pOut->f._02 = pM->f._02;
242        pOut->f._12 = pM->f._12;
243    }
244    return pOut;
245}
246
247NN_MATH_INLINE MTX23*
248MTX23Sub(MTX23* pOut, const MTX23* p1, const MTX23* p2)
249{
250    NN_NULL_ASSERT( pOut );
251    NN_NULL_ASSERT( p1 );
252    NN_NULL_ASSERT( p2 );
253
254    pOut->f._00 = p1->f._00 - p2->f._00;
255    pOut->f._01 = p1->f._01 - p2->f._01;
256    pOut->f._02 = p1->f._02 - p2->f._02;
257
258    pOut->f._10 = p1->f._10 - p2->f._10;
259    pOut->f._11 = p1->f._11 - p2->f._11;
260    pOut->f._12 = p1->f._12 - p2->f._12;
261
262    return pOut;
263}
264
265NN_MATH_INLINE MTX23*
266MTX23Translate(MTX23* pOut, const VEC2* pT)
267{
268    NN_NULL_ASSERT( pOut );
269    NN_NULL_ASSERT( pT );
270
271    f32 (*const m)[3] = pOut->m;
272
273    m[0][0] = 1.0f;  m[0][1] = 0.0f;  m[0][2] = pT->x;
274    m[1][0] = 0.0f;  m[1][1] = 1.0f;  m[1][2] = pT->y;
275
276    return pOut;
277}
278
279NN_MATH_INLINE MTX23*
280MTX23Zero(MTX23* pOut)
281{
282    NN_NULL_ASSERT( pOut );
283
284    pOut->f._00 = pOut->f._01 = pOut->f._02 =
285    pOut->f._10 = pOut->f._11 = pOut->f._12 = 0.f;
286
287    return pOut;
288}
289
290}  // namespace math
291}  // namespace nn
292