1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     math_Vector3.h
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: 25718 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_MATH_VECTOR3_H_
17 #define NN_MATH_VECTOR3_H_
18 
19 #include <cstring>
20 #include <nn/math/math_Config.h>
21 #include <nn/math/math_Constant.h>
22 
23 #pragma push
24 #pragma Otime
25 
26 namespace nn {
27 namespace math {
28 
29 struct VEC3;
30 struct MTX33;
31 struct MTX34;
32 
33 // (x, y, z, 0)として変換
34 NN_MATH_INLINE bool VEC3IsZero(const VEC3* p);
35 NN_MATH_INLINE VEC3* VEC3Maximize(VEC3* pOut, const VEC3* p1, const VEC3* p2);
36 NN_MATH_INLINE VEC3* VEC3Minimize(VEC3* pOut, const VEC3* p1, const VEC3* p2);
37 NN_MATH_INLINE VEC3* VEC3Cross(VEC3* pOut, const VEC3* p1, const VEC3* p2);
38 NN_MATH_INLINE VEC3* VEC3Normalize(VEC3* pOut, const VEC3* p);
39 NN_MATH_INLINE VEC3* VEC3SafeNormalize(VEC3* pOut, const VEC3* p, const VEC3& alt);
40 NN_MATH_INLINE f32   VEC3SquareDist(const VEC3* p1, const VEC3* p2);
41 
42 inline VEC3* VEC3Add(VEC3* pOut, const VEC3* p1, const VEC3* p2);
43 inline VEC3* VEC3Sub(VEC3* pOut, const VEC3* p1, const VEC3* p2);
44 inline VEC3* VEC3Mult(VEC3* pOut, const VEC3* p1, const VEC3* p2);
45 inline VEC3* VEC3Scale(VEC3* pOut, const VEC3* p, f32 scale);
46 inline VEC3* VEC3Lerp(VEC3* pOut, const VEC3* p1, const VEC3* p2, f32 t);
47 inline f32   VEC3Dot(const VEC3* p1, const VEC3* p2);
48 inline f32   VEC3Len(const VEC3* p);
49 inline f32   VEC3SquareLen(const VEC3* p);
50 inline f32   VEC3Dist(const VEC3* p1, const VEC3* p2);
51 
52 
53 NN_FORCE_INLINE VEC3* VEC3Normalize(VEC3* pOut, const VEC3* p);
54 
55 /* =======================================================================
56         クラスの定義
57    ======================================================================== */
58 struct VEC3_
59 {
60     f32 x;
61     f32 y;
62     f32 z;
63 };
64 
65 /*!------------------------------------------------------------------------
66     @brief        3次のベクトルクラスです。
67    ------------------------------------------------------------------------ */
68 struct VEC3 : public VEC3_
69 {
70 public:
71     static const int DIMENSION = 3; //!< 次元数です。
72 
73     //!< @brief ゼロベクトルです。
ZeroVEC374     static const VEC3& Zero()
75     {
76         static const VEC3 zero(0.0f, 0.0f, 0.0f);
77 
78         return zero;
79     }
80 
81     typedef VEC3 self_type; //!< 自分の型です
82     typedef f32  value_type; //!< 要素の型です。
83 public:
84     //----------------------------------------
85     //! @name 作成
86     //@{
87 
88     //! @brief コンストラクタです。
VEC3VEC389     VEC3() {}
VEC3VEC390     VEC3(const f32* p) { x = p[0]; y = p[1]; z = p[2]; }
91     //! @brief コピーコンストラクタです。
VEC3VEC392     VEC3(const VEC3_& v) { x = v.x; y = v.y; z = v.z; }
93     //! @brief コンストラクタです。
VEC3VEC394     VEC3(f32 fx, f32 fy, f32 fz) { x = fx; y = fy; z = fz; }
95 
96     //@}
97 
98     //----------------------------------------
99     //! @name 変換
100     //@{
101     //! @brief f32 型へのキャストです。
102     operator f32*() { return &x; }
103     //! @brief f32 型へのキャストです。
104     operator const f32*() const { return &x; }
105     //@}
106 
107     //----------------------------------------
108     //! @name 演算
109     //@{
110 
111     self_type& operator += (const self_type& rhs) { (void)VEC3Add(this, this, &rhs); return *this; }
112     self_type& operator -= (const self_type& rhs) { (void)VEC3Sub(this, this, &rhs); return *this; }
113     self_type& operator *= (const self_type& rhs) { (void)VEC3Mult(this, this, &rhs); return *this; }
114     self_type& operator *= (f32 f) { (void)VEC3Scale(this, this, f); return *this; }
115     self_type& operator /= (f32 f) { return operator*=(1.f / f); }
116 
117     self_type operator + () const { return *this; }
118     self_type operator - () const { return self_type(-x, -y, -z); }
119 
120     // 2項演算子は戻り値最適化が行われるかどうかで最適な実装が異なる
121     self_type operator + (const self_type& rhs) const { VEC3 tmp; (void)VEC3Add(&tmp, this, &rhs); return tmp; }
122     self_type operator - (const self_type& rhs) const { VEC3 tmp; (void)VEC3Sub(&tmp, this, &rhs); return tmp; }
123     self_type operator * (f32 f) const { VEC3 tmp; (void)VEC3Scale(&tmp, this, f); return tmp; }
124     self_type operator / (f32 f) const { f32 r = 1.f / f; return operator*(r); }
125 
126     //! @brief 2つのベクトル間の線形補間を計算し設定します。
127     //!
128     //! @param[in] lhs 線形補間の始点となるベクトルです。
129     //! @param[in] rhs 線形補間の終点となるベクトルです。
130     //! @param[in] t   線形補間のパラメータ。0.0 であれば lhs が 1.0 であれば rhs が結果となります。
131     //!
LerpVEC3132     self_type& Lerp(const VEC3& lhs, const VEC3& rhs, f32 t)
133     {
134         return *VEC3Lerp(this, &lhs, &rhs, t);
135     }
136 
137     //! @brief 指定したベクトルとの内積を計算します。
138     //!
139     //! @param[in] vec 内積を行うベクトルです。
140     //!
DotVEC3141     f32 Dot(const VEC3& vec) const
142     {
143         return VEC3Dot(this, &vec);
144     }
145 
146     //! @brief ベクトルの長さの2乗を計算します。
147     //! 将来削除される可能性がありますので非推奨です。
148     //! LengthSquareを推奨します。
LenSqVEC3149     f32 LenSq() const { return VEC3SquareLen(this); }
150 
151     //! @brief ベクトルの長さの2乗を計算します。
LengthSquareVEC3152     f32 LengthSquare() const { return VEC3SquareLen(this); }
153 
154     //! @brief ベクトルの長さを計算します。
LengthVEC3155     f32 Length() const { return VEC3Len(this); }
156 
157     //! @brief ベクトルを正規化します。
NormalizeVEC3158     self_type& Normalize()
159     {
160         return *VEC3Normalize(this, this);
161     }
162 
163     //! @brief ベクトルを正規化します。
164     //!        正規化に失敗した場合は指定されたベクトルを設定します。
165     //!
166     //! @param[in]    alt   正規化に失敗した場合に設定するベクトルです。
SafeNormalizeVEC3167     self_type& SafeNormalize(const VEC3& alt)
168     {
169         return *VEC3SafeNormalize(this, this, alt);
170     }
171 
172     //! @brief 指定したベクトルとの距離の二乗を計算します。
173     //!
174     //! @param[in] vec 距離を計算するベクトルです。
DistanceSquareVEC3175     f32 DistanceSquare(const VEC3& vec) const
176     {
177         return VEC3SquareDist(this, &vec);
178     }
179 
180     //! @brief 2つのベクトルのそれぞれの成分の最大値から構成されるベクトルを作成し設定します。
181     //!
182     //! @brief lhs 最大値を計算する左辺ベクトルです。
183     //! @brief rhs 最大値を計算する右辺ベクトルです。
MaximizeVEC3184     self_type& Maximize(const VEC3& lhs, const VEC3& rhs)
185     {
186         return *VEC3Maximize(this, &lhs, &rhs);
187     }
188 
189     //! @brief 2つのベクトルのそれぞれの成分の最小値から構成されるベクトルを作成し設定します。
190     //!
191     //! @brief lhs 最小値を計算する左辺ベクトルです。
192     //! @brief rhs 最小値を計算する右辺ベクトルです。
MinimizeVEC3193     self_type& Minimize(const VEC3& lhs, const VEC3& rhs)
194     {
195         return *VEC3Minimize(this, &lhs, &rhs);
196     }
197 
198     //! @brief ベクトルの外積を計算し設定します。
199     //!
200     //! @brief lhs 外積を計算する左辺ベクトルです。
201     //! @brief rhs 外積を計算する右辺ベクトルです。
CrossVEC3202     self_type& Cross(const VEC3& lhs, const VEC3& rhs)
203     {
204         return *VEC3Cross(this, &lhs, &rhs);
205     }
206 
207     //@}
208 
209     //----------------------------------------
210     //! @name 設定
211     //@{
212 
213     //! @brief 値を個別に設定します。
SetVEC3214     void Set(f32 fx, f32 fy, f32 fz) { x = fx; y = fy; z = fz; }
215 
216     //! @brief 値を設定します。
SetVEC3217     void Set(const self_type& value) { x = value.x; y = value.y; z = value.z; }
218 
219     //@}
220 
221     //----------------------------------------
222     //! @name 比較
223     //@{
224     //! @brief 同値であれば true を返します。
225     bool operator == (const self_type& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z; }
226 
227     //! @brief 同値でなければ true を返します。
228     bool operator != (const self_type& rhs) const { return x != rhs.x || y != rhs.y || z != rhs.z; }
229 
230     //! @brief ゼロベクトルであれば true を返します。
IsZeroVEC3231     bool IsZero() const { return VEC3IsZero(this); }
232 
233     //@}
234 
235     //! @brief 状態を出力します。
236     void Report(bool bNewline = true, const char* name = NULL) const;
237 };
238 
239 typedef struct VEC3 Vector3;
240 
241 /* ------------------------------------------------------------------------
242     VEC3用の関数
243    ------------------------------------------------------------------------ */
244 
245 /*!
246     @name    ベクトル
247     @{
248 */
249 
250 /*!--------------------------------------------------------------------------*
251   @brief        ベクトルの和を計算します。
252 
253   @param[out]   pOut  計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。
254   @param[in]    p1    左辺値へのポインタ
255   @param[in]    p2    右辺値へのポインタ
256 
257   @return       pOut を返します。
258  *---------------------------------------------------------------------------*/
259 inline VEC3*
VEC3Add(VEC3 * pOut,const VEC3 * p1,const VEC3 * p2)260 VEC3Add(VEC3* pOut, const VEC3* p1, const VEC3* p2)
261 {
262     pOut->x = p1->x + p2->x;
263     pOut->y = p1->y + p2->y;
264     pOut->z = p1->z + p2->z;
265     return pOut;
266 }
267 
268 
269 /*!--------------------------------------------------------------------------*
270   @brief        ベクトルの差を計算します。
271 
272   @param[out]   pOut  計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。
273   @param[in]    p1    左辺値へのポインタ
274   @param[in]    p2    右辺値へのポインタ
275 
276   @return       pOut を返します。
277  *---------------------------------------------------------------------------*/
278 inline VEC3*
VEC3Sub(VEC3 * pOut,const VEC3 * p1,const VEC3 * p2)279 VEC3Sub(VEC3* pOut, const VEC3* p1, const VEC3* p2)
280 {
281     pOut->x = p1->x - p2->x;
282     pOut->y = p1->y - p2->y;
283     pOut->z = p1->z - p2->z;
284     return pOut;
285 }
286 
287 /*!--------------------------------------------------------------------------*
288   @brief        ベクトルの積を計算します。
289 
290   @param[out]   pOut  計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。
291   @param[in]    p1    左辺値へのポインタ
292   @param[in]    p2    右辺値へのポインタ
293 
294   @return       pOut を返します。
295  *---------------------------------------------------------------------------*/
296 inline VEC3*
VEC3Mult(VEC3 * pOut,const VEC3 * p1,const VEC3 * p2)297 VEC3Mult(VEC3* pOut, const VEC3* p1, const VEC3* p2)
298 {
299     pOut->x = p1->x * p2->x;
300     pOut->y = p1->y * p2->y;
301     pOut->z = p1->z * p2->z;
302     return pOut;
303 }
304 
305 /*!--------------------------------------------------------------------------*
306   @brief        ベクトルのスカラー倍を計算します。
307 
308   @param[out]   pOut   計算結果を受け取るバッファへのポインタ。p と同じベクトルを指していても構いません。
309   @param[in]    p      左辺値へのポインタ
310   @param[in]    scale  掛ける数
311 
312   @return       pOut を返します。
313  *---------------------------------------------------------------------------*/
314 inline VEC3*
VEC3Scale(VEC3 * pOut,const VEC3 * p,f32 scale)315 VEC3Scale(VEC3* pOut, const VEC3* p, f32 scale)
316 {
317     pOut->x = scale * p->x;
318     pOut->y = scale * p->y;
319     pOut->z = scale * p->z;
320     return pOut;
321 }
322 
323 /*!--------------------------------------------------------------------------*
324   @brief        2つのベクトル間の線形補間を計算します。
325 
326   @param[out]   pOut  計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。
327   @param[in]    p1    線形補間の始点となるベクトルへのポインタ
328   @param[in]    p2    線形補間の終点となるベクトルへのポインタ
329   @param[in]    t     線形補間のパラメータ。0.0 であれば p1 が 1.0 であれば p2 が結果となります。
330 
331   @return       pOut を返します。
332  *---------------------------------------------------------------------------*/
333 inline VEC3*
VEC3Lerp(VEC3 * pOut,const VEC3 * p1,const VEC3 * p2,f32 t)334 VEC3Lerp(VEC3* pOut, const VEC3* p1, const VEC3* p2, f32 t)
335 {
336     pOut->x = p1->x + t * (p2->x - p1->x);
337     pOut->y = p1->y + t * (p2->y - p1->y);
338     pOut->z = p1->z + t * (p2->z - p1->z);
339     return pOut;
340 }
341 
342 /*!--------------------------------------------------------------------------*
343   @brief        ベクトルの内積を計算します。
344 
345   @param[in]    p1    左辺値へのポインタ
346   @param[in]    p2    右辺値へのポインタ
347 
348   @return       p1 と p2 の内積を返します。
349  *---------------------------------------------------------------------------*/
350 inline f32
VEC3Dot(const VEC3 * p1,const VEC3 * p2)351 VEC3Dot(const VEC3* p1, const VEC3* p2)
352 {
353     return p1->x * p2->x + p1->y * p2->y + p1->z * p2->z;
354 }
355 
356 
357 /*!--------------------------------------------------------------------------*
358   @brief        ベクトルの長さの2乗を計算します。
359 
360   @param[in]    p  対象のベクトルへのポインタ。
361 
362   @return       p の長さの2乗を返します。
363  *---------------------------------------------------------------------------*/
364 inline f32
VEC3SquareLen(const VEC3 * p)365 VEC3SquareLen(const VEC3* p)
366 {
367     return p->x * p->x + p->y * p->y + p->z * p->z;
368 }
369 
370 /*!--------------------------------------------------------------------------*
371   @brief        ベクトルの長さを計算します。
372 
373   @param[in]    p  対象のベクトルへのポインタ。
374 
375   @return       p の長さを返します。
376  *---------------------------------------------------------------------------*/
377 inline f32
VEC3Len(const VEC3 * p)378 VEC3Len(const VEC3* p)
379 {
380     NN_NULL_ASSERT( p );
381 
382     return ::std::sqrtf( VEC3SquareLen( p ) );
383 }
384 
385 
386 /*!--------------------------------------------------------------------------*
387   @brief        2つのベクトル間の距離を計算します。
388 
389   @param[in]    p1    左辺値へのポインタ
390   @param[in]    p2    右辺値へのポインタ
391 
392   @return       p1 と p2 の距離を返します。
393  *---------------------------------------------------------------------------*/
394 inline f32
VEC3Dist(const VEC3 * p1,const VEC3 * p2)395 VEC3Dist( const VEC3* p1, const VEC3* p2 )
396 {
397     NN_NULL_ASSERT( p1 );
398     NN_NULL_ASSERT( p2 );
399 
400     return ::std::sqrtf( VEC3SquareDist( p1, p2 ) );
401 }
402 
403 
404 inline VEC3
405 operator * (f32 f, const VEC3& rhs) { VEC3 tmp; (void)VEC3Scale(&tmp, &rhs, f); return tmp; }
406 
407 }  // namespace math
408 }  // namespace nn
409 
410 #include <nn/math/ARMv6/math_Vector3.h>
411 
412 namespace nn {
413 namespace math {
414 
415 /*!
416     @name    ベクトル
417     @{
418 */
419 
420 /*!--------------------------------------------------------------------------*
421   @brief        ベクトルを正規化します。
422 
423   @param[out]   pOut  計算結果を受け取るバッファへのポインタ。p と同じベクトルを指していても構いません。
424   @param[in]    p     対象のベクトルへのポインタ
425 
426   @return       pOut を返します。
427  *---------------------------------------------------------------------------*/
428 NN_FORCE_INLINE VEC3*
VEC3Normalize(VEC3 * pOut,const VEC3 * p)429 VEC3Normalize(VEC3* pOut, const VEC3* p)
430 {
431 #if defined( NN_HARDWARE_CTR )
432     #if (VEC3NORMALIZE__CONFIG == D_ORG)
433         return ARMv6::VEC3NormalizeC(pOut, p);
434     #elif (VEC3NORMALIZE__CONFIG == D_FAST_C)
435         return ARMv6::VEC3NormalizeC_FAST(pOut, p);
436     #elif (VEC3NORMALIZE__CONFIG == D_FAST_ASM)
437     #elif (VEC3NORMALIZE__CONFIG == D_FAST_C_ALGO)
438     #elif (VEC3NORMALIZE__CONFIG == D_FAST_ASM_ALGO)
439     #endif
440 #else
441 #endif // #if defined( NN_HARDWARE_CTR )
442 }
443 
444 /*!
445     @}
446 */
447 
448 }  // namespace math
449 }  // namespace nn
450 
451 
452 
453 #if defined(NN_MATH_AS_INLINE)
454 #include <nn/math/inline/math_Vector3.ipp>
455 #include <nn/math/ARMv6/inline/math_Vector3.ipp>
456 #endif
457 
458 namespace nn {
459 namespace math {
460 
461 //-- const 引数を参照にしたオーバーロード
VEC3IsZero(const VEC3 & v)462 inline bool VEC3IsZero(const VEC3& v){ return VEC3IsZero( &v ); }
VEC3Maximize(VEC3 * pOut,const VEC3 & v1,const VEC3 & v2)463 inline VEC3* VEC3Maximize(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Maximize( pOut, &v1, &v2 ); }
VEC3Minimize(VEC3 * pOut,const VEC3 & v1,const VEC3 & v2)464 inline VEC3* VEC3Minimize(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Minimize( pOut, &v1, &v2 ); }
VEC3Cross(VEC3 * pOut,const VEC3 & v1,const VEC3 & v2)465 inline VEC3* VEC3Cross(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Cross( pOut, &v1, &v2 ); }
VEC3Normalize(VEC3 * pOut,const VEC3 & v)466 inline VEC3* VEC3Normalize(VEC3* pOut, const VEC3& v) { return VEC3Normalize( pOut, &v ); }
VEC3SafeNormalize(VEC3 * pOut,const VEC3 & v,const VEC3 & alt)467 inline VEC3* VEC3SafeNormalize(VEC3* pOut, const VEC3& v, const VEC3& alt) { return VEC3SafeNormalize( pOut, &v, alt ); }
VEC3SquareDist(const VEC3 & v1,const VEC3 & v2)468 inline f32   VEC3SquareDist(const VEC3& v1, const VEC3& v2) { return VEC3SquareDist( &v1, &v2 ); }
469 
VEC3Add(VEC3 * pOut,const VEC3 & v1,const VEC3 & v2)470 inline VEC3* VEC3Add(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Add( pOut, &v1, &v2 ); }
VEC3Sub(VEC3 * pOut,const VEC3 & v1,const VEC3 & v2)471 inline VEC3* VEC3Sub(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Sub( pOut, &v1, &v2 ); }
VEC3Mult(VEC3 * pOut,const VEC3 & v1,const VEC3 & v2)472 inline VEC3* VEC3Mult(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Mult( pOut, &v1, &v2 ); }
VEC3Scale(VEC3 * pOut,const VEC3 & v,f32 scale)473 inline VEC3* VEC3Scale(VEC3* pOut, const VEC3& v, f32 scale) { return VEC3Scale( pOut, &v, scale ); }
VEC3Lerp(VEC3 * pOut,const VEC3 & v1,const VEC3 & v2,f32 t)474 inline VEC3* VEC3Lerp(VEC3* pOut, const VEC3& v1, const VEC3& v2, f32 t) { return VEC3Lerp( pOut, &v1, &v2, t ); }
VEC3Dot(const VEC3 & v1,const VEC3 & v2)475 inline f32   VEC3Dot(const VEC3& v1, const VEC3& v2) { return VEC3Dot( &v1, &v2 ); }
VEC3Len(const VEC3 & v)476 inline f32   VEC3Len(const VEC3& v) { return VEC3Len( &v ); }
VEC3SquareLen(const VEC3 & v)477 inline f32   VEC3SquareLen(const VEC3& v) { return VEC3SquareLen( &v ); }
VEC3Dist(const VEC3 & v1,const VEC3 & v2)478 inline f32   VEC3Dist(const VEC3& v1, const VEC3& v2) { return VEC3Dist( &v1, &v2 ); }
479 
480 }  // namespace math
481 }  // namespace nn
482 
483 #pragma pop
484 
485 #endif
486