/*---------------------------------------------------------------------------* Project: Horizon File: math_Vector2.h Copyright (C)2009-2010 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 18015 $ *---------------------------------------------------------------------------*/ #ifndef NN_MATH_VECTOR2_H_ #define NN_MATH_VECTOR2_H_ #include #include #pragma push #pragma Otime namespace nn { namespace math { struct VEC2; struct MTX23; NN_MATH_INLINE bool VEC2IsZero(const VEC2* p); NN_MATH_INLINE VEC2* VEC2Lerp(VEC2* pOut, const VEC2* p1, const VEC2* p2, f32 t); NN_MATH_INLINE f32 VEC2Dot(const VEC2* p1, const VEC2* p2); NN_MATH_INLINE VEC2* VEC2Maximize(VEC2* pOut, const VEC2* p1, const VEC2* p2); NN_MATH_INLINE VEC2* VEC2Minimize(VEC2* pOut, const VEC2* p1, const VEC2* p2); NN_MATH_INLINE VEC2* VEC2Normalize(VEC2* pOut, const VEC2* p); NN_MATH_INLINE VEC2* VEC2SafeNormalize(VEC2* pOut, const VEC2* p, const VEC2& alt); NN_MATH_INLINE f32 VEC2DistSq(const VEC2* p1, const VEC2* p2); NN_MATH_INLINE VEC2* VEC2Transform(VEC2* pOut, const MTX23* pM, const VEC2* pV); /* ======================================================================= クラスの定義 ======================================================================== */ struct VEC2_ { f32 x; f32 y; }; /*!------------------------------------------------------------------------ @brief 2次のベクトルクラスです。 ------------------------------------------------------------------------ */ struct VEC2 : public VEC2_ { public: static const int DIMENSION = 2; //!< 次元数です。 //!< @brief ゼロベクトルです。 static const VEC2& Zero() { static const VEC2 zero(0.0f, 0.0f); return zero; } typedef VEC2 self_type; //!< 自分の型です typedef f32 value_type; //!< 要素の型です。 public: //---------------------------------------- //! @name 作成 //@{ //! @brief コンストラクタです。 VEC2() {} //! @brief コンストラクタです。 VEC2(const f32* p) { x = p[0]; y = p[1]; } //! @brief コピーコンストラクタです。 VEC2(const VEC2_& v) { x = v.x; y = v.y; } //! @brief コンストラクタです。 VEC2(f32 fx, f32 fy) { x = fx; y = fy; } //@} //---------------------------------------- //! @name 変換 //@{ //! @brief f32 型へのキャストです。 operator f32*() { return &x; } //! @brief f32 型へのキャストです。 operator const f32*() const { return &x; } //@} //---------------------------------------- //! @name 演算 //@{ self_type& operator += (const self_type& rhs) { x += rhs.x; y += rhs.y; return *this; } self_type& operator -= (const self_type& rhs) { x -= rhs.x; y -= rhs.y; return *this; } self_type& operator *= (const self_type& rhs) { x *= rhs.x; y *= rhs.y; return *this; } self_type& operator *= (f32 f) { x *= f; y *= f; return *this; } self_type& operator /= (f32 f) { f32 r = 1.f / f; x *= r; y *= r; return *this; } self_type operator + () const { return *this; } self_type operator - () const { return self_type(-x, -y); } self_type operator + (const self_type& rhs) const { return self_type(x + rhs.x, y + rhs.y); } self_type operator - (const self_type& rhs) const { return self_type(x - rhs.x, y - rhs.y); } self_type operator * (f32 f) const { return self_type(f * x, f * y); } self_type operator / (f32 f) const { f32 r = 1.f / f; return self_type(r * x, r * y); } //! @brief 2つのベクトル間の線形補間を計算し設定します。 //! //! @param[in] lhs 線形補間の始点となるベクトルです。 //! @param[in] rhs 線形補間の終点となるベクトルです。 //! @param[in] t 線形補間のパラメータ。0.0 であれば lhs が 1.0 であれば rhs が結果となります。 //! self_type& Lerp(const VEC2& lhs, const VEC2& rhs, f32 t) { return *VEC2Lerp(this, &lhs, &rhs, t); } //! @brief 指定したベクトルとの内積を計算します。 //! //! @param[in] vec 内積を行うベクトルです。 //! f32 Dot(const VEC2& vec) const { return VEC2Dot(this, &vec); } //! @brief ベクトルの長さの2乗を計算します。 f32 LenSq() const { return x * x + y * y; } //! @brief ベクトルの長さの2乗を計算します。 f32 LengthSquare() const { return x * x + y * y; } //! @brief ベクトルの長さを計算します。 f32 Length() const { return FSqrt(this->x * this->x + this->y * this->y); } //! @brief ベクトルを正規化します。 self_type& Normalize() { return *VEC2Normalize(this, this); } //! @brief ベクトルを正規化します。 //! 正規化に失敗した場合は指定されたベクトルを設定します。 //! //! @param[in] alt 正規化に失敗した場合に設定するベクトルです。 self_type& SafeNormalize(const VEC2& alt) { return *VEC2SafeNormalize(this, this, alt); } //! @brief 指定したベクトルとの距離の二乗を計算します。 //! //! @param[in] vec 距離を計算するベクトルです。 f32 DistanceSquare(const VEC2& vec) { return VEC2DistSq(this, &vec); } //! @brief 2つのベクトルのそれぞれの成分の最大値から構成されるベクトルを作成し設定します。 //! //! @brief lhs 最大値を計算する左辺ベクトルです。 //! @brief rhs 最大値を計算する右辺ベクトルです。 self_type& Maximize(const VEC2& lhs, const VEC2& rhs) { return *VEC2Maximize(this, &lhs, &rhs); } //! @brief 2つのベクトルのそれぞれの成分の最小値から構成されるベクトルを作成し設定します。 //! //! @brief lhs 最小値を計算する左辺ベクトルです。 //! @brief rhs 最小値を計算する右辺ベクトルです。 self_type& Minimize(const VEC2& lhs, const VEC2& rhs) { return *VEC2Minimize(this, &lhs, &rhs); } //@} //---------------------------------------- //! @name 設定 //@{ //! @brief 値を個別に設定します。 void Set(f32 fx, f32 fy) { x = fx; y = fy; } //@} //---------------------------------------- //! @name 比較 //@{ //! @brief 同値であれば true を返します。 bool operator == (const self_type& rhs) const { return x == rhs.x && y == rhs.y; } //! @brief 同値であれば true を返します。 bool operator != (const self_type& rhs) const { return x != rhs.x || y != rhs.y; } //! @brief ゼロベクトルであれば true を返します。 bool IsZero() const { return VEC2IsZero(this); } //@} //! @brief 状態を出力します。 void Report(bool bNewline = true, const char* name = NULL) const; }; typedef struct VEC2 Vector2; /* ------------------------------------------------------------------------ VEC2用の関数 ------------------------------------------------------------------------ */ /*! @name ベクトル @{ */ /*!--------------------------------------------------------------------------* @brief ベクトルの和を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC2* VEC2Add(VEC2* pOut, const VEC2* p1, const VEC2* p2) { NN_NULL_ASSERT( pOut ); NN_NULL_ASSERT( p1 ); NN_NULL_ASSERT( p2 ); pOut->x = p1->x + p2->x; pOut->y = p1->y + p2->y; return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルの差を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC2* VEC2Sub(VEC2* pOut, const VEC2* p1, const VEC2* p2) { NN_NULL_ASSERT( pOut ); NN_NULL_ASSERT( p1 ); NN_NULL_ASSERT( p2 ); pOut->x = p1->x - p2->x; pOut->y = p1->y - p2->y; return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルの積を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC2* VEC2Mult(VEC2* pOut, const VEC2* p1, const VEC2* p2) { pOut->x = p1->x * p2->x; pOut->y = p1->y * p2->y; return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルのスカラー倍を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じベクトルを指していても構いません。 @param[in] p 左辺値へのポインタ @param[in] scale 掛ける数 @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC2* VEC2Scale(VEC2* pOut, const VEC2* p, f32 scale) { NN_NULL_ASSERT( pOut ); NN_NULL_ASSERT( p ); pOut->x = p->x * scale; pOut->y = p->y * scale; return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトル間の線形補間を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 線形補間の始点となるベクトルへのポインタ @param[in] p2 線形補間の終点となるベクトルへのポインタ @param[in] t 線形補間のパラメータ。0.0 であれば p1 が 1.0 であれば p2 が結果となります。 @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC2* VEC2Lerp(VEC2* pOut, const VEC2* p1, const VEC2* p2, f32 t) { // (1-t)*p1 + t*p2 pOut->x = p1->x + t * (p2->x - p1->x); pOut->y = p1->y + t * (p2->y - p1->y); return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルの内積を計算します。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return p1 と p2 の内積を返します。 *---------------------------------------------------------------------------*/ inline f32 VEC2Dot(const VEC2* p1, const VEC2* p2) { NN_NULL_ASSERT( p1 ); NN_NULL_ASSERT( p2 ); return p1->x * p2->x + p1->y * p2->y; } /*!--------------------------------------------------------------------------* @brief ベクトルの長さの2乗を計算します。 @param[in] p 対象のベクトルへのポインタ。 @return p の長さの2乗を返します。 *---------------------------------------------------------------------------*/ inline f32 VEC2LenSq(const VEC2* p) { NN_NULL_ASSERT( p ); return p->x * p->x + p->y * p->y; } /*!--------------------------------------------------------------------------* @brief ベクトルの長さを計算します。 @param[in] p 対象のベクトルへのポインタ。 @return p の長さを返します。 *---------------------------------------------------------------------------*/ inline f32 VEC2Len(const VEC2* p) { return FSqrt(p->x * p->x + p->y * p->y); } /*!--------------------------------------------------------------------------* @brief 2つのベクトル間の距離の2乗を計算します。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return p1 と p2 の距離の2乗を返します。 *---------------------------------------------------------------------------*/ inline f32 VEC2DistSq(const VEC2* p1, const VEC2* p2) { VEC2 tmp; return VEC2LenSq(VEC2Sub(&tmp, p1, p2)); } inline VEC2 operator * (f32 f, const VEC2& rhs) { return VEC2(f * rhs.x, f * rhs.y); } /*! @} */ } // namespace math } // namespace nn #if defined(NN_MATH_AS_INLINE) #include #endif namespace nn { namespace math { //-- const 引数を参照にしたオーバーロード inline bool VEC2IsZero(const VEC2& v){ return VEC2IsZero( &v ); } inline VEC2* VEC2Add(VEC2* pOut, const VEC2& p1, const VEC2& p2) { return VEC2Add(pOut, &p1, &p2); } inline VEC2* VEC2Sub(VEC2* pOut, const VEC2& v1, const VEC2& v2) { return VEC2Sub(pOut, &v1, &v2); } inline VEC2* VEC2Mult(VEC2* pOut, const VEC2& v1, const VEC2& v2) { return VEC2Mult(pOut, &v1, &v2); } inline VEC2* VEC2Scale(VEC2* pOut, const VEC2& v, f32 scale) { return VEC2Scale(pOut, &v, scale); } inline VEC2* VEC2Lerp(VEC2* pOut, const VEC2& v1, const VEC2& v2, f32 t) { return VEC2Lerp(pOut, &v1, &v2, t); } inline f32 VEC2Dot(const VEC2& v1, const VEC2& v2) { return VEC2Dot(&v1, &v2); } inline f32 VEC2LenSq(const VEC2& v) { return VEC2LenSq( &v ); } inline f32 VEC2Len(const VEC2& v) { return VEC2Len( &v ); } inline f32 VEC2DistSq(const VEC2& v1, const VEC2& v2) { return VEC2DistSq( &v1, &v2 ); } inline VEC2* VEC2Maximize(VEC2* pOut, const VEC2& v1, const VEC2& v2) { return VEC2Maximize( pOut, &v1, &v2 ); } inline VEC2* VEC2Minimize(VEC2* pOut, const VEC2& v1, const VEC2& v2) { return VEC2Minimize( pOut, &v1, &v2 ); } inline VEC2* VEC2Normalize(VEC2* pOut, const VEC2& v) { return VEC2Normalize( pOut, &v ); } inline VEC2* VEC2SafeNormalize(VEC2* pOut, const VEC2& v, const VEC2& alt) { return VEC2SafeNormalize( pOut, &v, alt ); } inline VEC2* VEC2Transform(VEC2* pOut, const MTX23& m, const VEC2& v) { return VEC2Transform( pOut, &m, &v ); } } // namespace math } // namespace nn #pragma pop #endif