/*---------------------------------------------------------------------------* Project: Horizon File: math_Vector3.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: 25718 $ *---------------------------------------------------------------------------*/ #ifndef NN_MATH_VECTOR3_H_ #define NN_MATH_VECTOR3_H_ #include #include #include #pragma push #pragma Otime namespace nn { namespace math { struct VEC3; struct MTX33; struct MTX34; // (x, y, z, 0)として変換 NN_MATH_INLINE bool VEC3IsZero(const VEC3* p); NN_MATH_INLINE VEC3* VEC3Maximize(VEC3* pOut, const VEC3* p1, const VEC3* p2); NN_MATH_INLINE VEC3* VEC3Minimize(VEC3* pOut, const VEC3* p1, const VEC3* p2); NN_MATH_INLINE VEC3* VEC3Cross(VEC3* pOut, const VEC3* p1, const VEC3* p2); NN_MATH_INLINE VEC3* VEC3Normalize(VEC3* pOut, const VEC3* p); NN_MATH_INLINE VEC3* VEC3SafeNormalize(VEC3* pOut, const VEC3* p, const VEC3& alt); NN_MATH_INLINE f32 VEC3SquareDist(const VEC3* p1, const VEC3* p2); inline VEC3* VEC3Add(VEC3* pOut, const VEC3* p1, const VEC3* p2); inline VEC3* VEC3Sub(VEC3* pOut, const VEC3* p1, const VEC3* p2); inline VEC3* VEC3Mult(VEC3* pOut, const VEC3* p1, const VEC3* p2); inline VEC3* VEC3Scale(VEC3* pOut, const VEC3* p, f32 scale); inline VEC3* VEC3Lerp(VEC3* pOut, const VEC3* p1, const VEC3* p2, f32 t); inline f32 VEC3Dot(const VEC3* p1, const VEC3* p2); inline f32 VEC3Len(const VEC3* p); inline f32 VEC3SquareLen(const VEC3* p); inline f32 VEC3Dist(const VEC3* p1, const VEC3* p2); NN_FORCE_INLINE VEC3* VEC3Normalize(VEC3* pOut, const VEC3* p); /* ======================================================================= クラスの定義 ======================================================================== */ struct VEC3_ { f32 x; f32 y; f32 z; }; /*!------------------------------------------------------------------------ @brief 3次のベクトルクラスです。 ------------------------------------------------------------------------ */ struct VEC3 : public VEC3_ { public: static const int DIMENSION = 3; //!< 次元数です。 //!< @brief ゼロベクトルです。 static const VEC3& Zero() { static const VEC3 zero(0.0f, 0.0f, 0.0f); return zero; } typedef VEC3 self_type; //!< 自分の型です typedef f32 value_type; //!< 要素の型です。 public: //---------------------------------------- //! @name 作成 //@{ //! @brief コンストラクタです。 VEC3() {} VEC3(const f32* p) { x = p[0]; y = p[1]; z = p[2]; } //! @brief コピーコンストラクタです。 VEC3(const VEC3_& v) { x = v.x; y = v.y; z = v.z; } //! @brief コンストラクタです。 VEC3(f32 fx, f32 fy, f32 fz) { x = fx; y = fy; z = fz; } //@} //---------------------------------------- //! @name 変換 //@{ //! @brief f32 型へのキャストです。 operator f32*() { return &x; } //! @brief f32 型へのキャストです。 operator const f32*() const { return &x; } //@} //---------------------------------------- //! @name 演算 //@{ self_type& operator += (const self_type& rhs) { (void)VEC3Add(this, this, &rhs); return *this; } self_type& operator -= (const self_type& rhs) { (void)VEC3Sub(this, this, &rhs); return *this; } self_type& operator *= (const self_type& rhs) { (void)VEC3Mult(this, this, &rhs); return *this; } self_type& operator *= (f32 f) { (void)VEC3Scale(this, this, f); return *this; } self_type& operator /= (f32 f) { return operator*=(1.f / f); } self_type operator + () const { return *this; } self_type operator - () const { return self_type(-x, -y, -z); } // 2項演算子は戻り値最適化が行われるかどうかで最適な実装が異なる self_type operator + (const self_type& rhs) const { VEC3 tmp; (void)VEC3Add(&tmp, this, &rhs); return tmp; } self_type operator - (const self_type& rhs) const { VEC3 tmp; (void)VEC3Sub(&tmp, this, &rhs); return tmp; } self_type operator * (f32 f) const { VEC3 tmp; (void)VEC3Scale(&tmp, this, f); return tmp; } self_type operator / (f32 f) const { f32 r = 1.f / f; return operator*(r); } //! @brief 2つのベクトル間の線形補間を計算し設定します。 //! //! @param[in] lhs 線形補間の始点となるベクトルです。 //! @param[in] rhs 線形補間の終点となるベクトルです。 //! @param[in] t 線形補間のパラメータ。0.0 であれば lhs が 1.0 であれば rhs が結果となります。 //! self_type& Lerp(const VEC3& lhs, const VEC3& rhs, f32 t) { return *VEC3Lerp(this, &lhs, &rhs, t); } //! @brief 指定したベクトルとの内積を計算します。 //! //! @param[in] vec 内積を行うベクトルです。 //! f32 Dot(const VEC3& vec) const { return VEC3Dot(this, &vec); } //! @brief ベクトルの長さの2乗を計算します。 //! 将来削除される可能性がありますので非推奨です。 //! LengthSquareを推奨します。 f32 LenSq() const { return VEC3SquareLen(this); } //! @brief ベクトルの長さの2乗を計算します。 f32 LengthSquare() const { return VEC3SquareLen(this); } //! @brief ベクトルの長さを計算します。 f32 Length() const { return VEC3Len(this); } //! @brief ベクトルを正規化します。 self_type& Normalize() { return *VEC3Normalize(this, this); } //! @brief ベクトルを正規化します。 //! 正規化に失敗した場合は指定されたベクトルを設定します。 //! //! @param[in] alt 正規化に失敗した場合に設定するベクトルです。 self_type& SafeNormalize(const VEC3& alt) { return *VEC3SafeNormalize(this, this, alt); } //! @brief 指定したベクトルとの距離の二乗を計算します。 //! //! @param[in] vec 距離を計算するベクトルです。 f32 DistanceSquare(const VEC3& vec) const { return VEC3SquareDist(this, &vec); } //! @brief 2つのベクトルのそれぞれの成分の最大値から構成されるベクトルを作成し設定します。 //! //! @brief lhs 最大値を計算する左辺ベクトルです。 //! @brief rhs 最大値を計算する右辺ベクトルです。 self_type& Maximize(const VEC3& lhs, const VEC3& rhs) { return *VEC3Maximize(this, &lhs, &rhs); } //! @brief 2つのベクトルのそれぞれの成分の最小値から構成されるベクトルを作成し設定します。 //! //! @brief lhs 最小値を計算する左辺ベクトルです。 //! @brief rhs 最小値を計算する右辺ベクトルです。 self_type& Minimize(const VEC3& lhs, const VEC3& rhs) { return *VEC3Minimize(this, &lhs, &rhs); } //! @brief ベクトルの外積を計算し設定します。 //! //! @brief lhs 外積を計算する左辺ベクトルです。 //! @brief rhs 外積を計算する右辺ベクトルです。 self_type& Cross(const VEC3& lhs, const VEC3& rhs) { return *VEC3Cross(this, &lhs, &rhs); } //@} //---------------------------------------- //! @name 設定 //@{ //! @brief 値を個別に設定します。 void Set(f32 fx, f32 fy, f32 fz) { x = fx; y = fy; z = fz; } //! @brief 値を設定します。 void Set(const self_type& value) { x = value.x; y = value.y; z = value.z; } //@} //---------------------------------------- //! @name 比較 //@{ //! @brief 同値であれば true を返します。 bool operator == (const self_type& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z; } //! @brief 同値でなければ true を返します。 bool operator != (const self_type& rhs) const { return x != rhs.x || y != rhs.y || z != rhs.z; } //! @brief ゼロベクトルであれば true を返します。 bool IsZero() const { return VEC3IsZero(this); } //@} //! @brief 状態を出力します。 void Report(bool bNewline = true, const char* name = NULL) const; }; typedef struct VEC3 Vector3; /* ------------------------------------------------------------------------ VEC3用の関数 ------------------------------------------------------------------------ */ /*! @name ベクトル @{ */ /*!--------------------------------------------------------------------------* @brief ベクトルの和を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC3* VEC3Add(VEC3* pOut, const VEC3* p1, const VEC3* p2) { pOut->x = p1->x + p2->x; pOut->y = p1->y + p2->y; pOut->z = p1->z + p2->z; return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルの差を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC3* VEC3Sub(VEC3* pOut, const VEC3* p1, const VEC3* p2) { pOut->x = p1->x - p2->x; pOut->y = p1->y - p2->y; pOut->z = p1->z - p2->z; return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルの積を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC3* VEC3Mult(VEC3* pOut, const VEC3* p1, const VEC3* p2) { pOut->x = p1->x * p2->x; pOut->y = p1->y * p2->y; pOut->z = p1->z * p2->z; return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルのスカラー倍を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じベクトルを指していても構いません。 @param[in] p 左辺値へのポインタ @param[in] scale 掛ける数 @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC3* VEC3Scale(VEC3* pOut, const VEC3* p, f32 scale) { pOut->x = scale * p->x; pOut->y = scale * p->y; pOut->z = scale * p->z; return pOut; } /*!--------------------------------------------------------------------------* @brief 2つのベクトル間の線形補間を計算します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p1, p2 と同じベクトルを指していても構いません。 @param[in] p1 線形補間の始点となるベクトルへのポインタ @param[in] p2 線形補間の終点となるベクトルへのポインタ @param[in] t 線形補間のパラメータ。0.0 であれば p1 が 1.0 であれば p2 が結果となります。 @return pOut を返します。 *---------------------------------------------------------------------------*/ inline VEC3* VEC3Lerp(VEC3* pOut, const VEC3* p1, const VEC3* p2, f32 t) { pOut->x = p1->x + t * (p2->x - p1->x); pOut->y = p1->y + t * (p2->y - p1->y); pOut->z = p1->z + t * (p2->z - p1->z); return pOut; } /*!--------------------------------------------------------------------------* @brief ベクトルの内積を計算します。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return p1 と p2 の内積を返します。 *---------------------------------------------------------------------------*/ inline f32 VEC3Dot(const VEC3* p1, const VEC3* p2) { return p1->x * p2->x + p1->y * p2->y + p1->z * p2->z; } /*!--------------------------------------------------------------------------* @brief ベクトルの長さの2乗を計算します。 @param[in] p 対象のベクトルへのポインタ。 @return p の長さの2乗を返します。 *---------------------------------------------------------------------------*/ inline f32 VEC3SquareLen(const VEC3* p) { return p->x * p->x + p->y * p->y + p->z * p->z; } /*!--------------------------------------------------------------------------* @brief ベクトルの長さを計算します。 @param[in] p 対象のベクトルへのポインタ。 @return p の長さを返します。 *---------------------------------------------------------------------------*/ inline f32 VEC3Len(const VEC3* p) { NN_NULL_ASSERT( p ); return ::std::sqrtf( VEC3SquareLen( p ) ); } /*!--------------------------------------------------------------------------* @brief 2つのベクトル間の距離を計算します。 @param[in] p1 左辺値へのポインタ @param[in] p2 右辺値へのポインタ @return p1 と p2 の距離を返します。 *---------------------------------------------------------------------------*/ inline f32 VEC3Dist( const VEC3* p1, const VEC3* p2 ) { NN_NULL_ASSERT( p1 ); NN_NULL_ASSERT( p2 ); return ::std::sqrtf( VEC3SquareDist( p1, p2 ) ); } inline VEC3 operator * (f32 f, const VEC3& rhs) { VEC3 tmp; (void)VEC3Scale(&tmp, &rhs, f); return tmp; } } // namespace math } // namespace nn #include namespace nn { namespace math { /*! @name ベクトル @{ */ /*!--------------------------------------------------------------------------* @brief ベクトルを正規化します。 @param[out] pOut 計算結果を受け取るバッファへのポインタ。p と同じベクトルを指していても構いません。 @param[in] p 対象のベクトルへのポインタ @return pOut を返します。 *---------------------------------------------------------------------------*/ NN_FORCE_INLINE VEC3* VEC3Normalize(VEC3* pOut, const VEC3* p) { #if defined( NN_HARDWARE_CTR ) #if (VEC3NORMALIZE__CONFIG == D_ORG) return ARMv6::VEC3NormalizeC(pOut, p); #elif (VEC3NORMALIZE__CONFIG == D_FAST_C) return ARMv6::VEC3NormalizeC_FAST(pOut, p); #elif (VEC3NORMALIZE__CONFIG == D_FAST_ASM) #elif (VEC3NORMALIZE__CONFIG == D_FAST_C_ALGO) #elif (VEC3NORMALIZE__CONFIG == D_FAST_ASM_ALGO) #endif #else #endif // #if defined( NN_HARDWARE_CTR ) } /*! @} */ } // namespace math } // namespace nn #if defined(NN_MATH_AS_INLINE) #include #include #endif namespace nn { namespace math { //-- const 引数を参照にしたオーバーロード inline bool VEC3IsZero(const VEC3& v){ return VEC3IsZero( &v ); } inline VEC3* VEC3Maximize(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Maximize( pOut, &v1, &v2 ); } inline VEC3* VEC3Minimize(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Minimize( pOut, &v1, &v2 ); } inline VEC3* VEC3Cross(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Cross( pOut, &v1, &v2 ); } inline VEC3* VEC3Normalize(VEC3* pOut, const VEC3& v) { return VEC3Normalize( pOut, &v ); } inline VEC3* VEC3SafeNormalize(VEC3* pOut, const VEC3& v, const VEC3& alt) { return VEC3SafeNormalize( pOut, &v, alt ); } inline f32 VEC3SquareDist(const VEC3& v1, const VEC3& v2) { return VEC3SquareDist( &v1, &v2 ); } inline VEC3* VEC3Add(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Add( pOut, &v1, &v2 ); } inline VEC3* VEC3Sub(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Sub( pOut, &v1, &v2 ); } inline VEC3* VEC3Mult(VEC3* pOut, const VEC3& v1, const VEC3& v2) { return VEC3Mult( pOut, &v1, &v2 ); } inline VEC3* VEC3Scale(VEC3* pOut, const VEC3& v, f32 scale) { return VEC3Scale( pOut, &v, scale ); } inline VEC3* VEC3Lerp(VEC3* pOut, const VEC3& v1, const VEC3& v2, f32 t) { return VEC3Lerp( pOut, &v1, &v2, t ); } inline f32 VEC3Dot(const VEC3& v1, const VEC3& v2) { return VEC3Dot( &v1, &v2 ); } inline f32 VEC3Len(const VEC3& v) { return VEC3Len( &v ); } inline f32 VEC3SquareLen(const VEC3& v) { return VEC3SquareLen( &v ); } inline f32 VEC3Dist(const VEC3& v1, const VEC3& v2) { return VEC3Dist( &v1, &v2 ); } } // namespace math } // namespace nn #pragma pop #endif