/// Clamp the roll angle to a range of +/-limit. inline Euler &limitRoll(const Radian &limit) { limitAngle(mRoll, limit); return *this; }
/// Clamp the yaw angle to a range of +/-limit. inline Euler &limitYaw(const Radian &limit) { limitAngle(mYaw, limit); return *this; }
/// Clamp the pitch angle to a range of +/-limit. inline Euler &limitPitch(const Radian &limit) { limitAngle(mPitch, limit); return *this; }
//====== // 更新 //====== void cPMDIK::update( void ) { Vector3 vec3OrgTargetPos; vec3OrgTargetPos.x = m_pTargetBone->m_matLocal[3][0]; vec3OrgTargetPos.y = m_pTargetBone->m_matLocal[3][1]; vec3OrgTargetPos.z = m_pTargetBone->m_matLocal[3][2]; Vector3 vec3EffPos; Vector3 vec3TargetPos; for( short i = m_cbNumLink - 1 ; i >= 0 ; i-- ){ m_ppBoneList[i]->updateMatrix(); } m_pEffBone->updateMatrix(); for( unsigned short it = 0 ; it < m_unCount ; it++ ) { for( unsigned char cbLinkIdx = 0 ; cbLinkIdx < m_cbNumLink ; cbLinkIdx++ ) { // エフェクタの位置の取得 vec3EffPos.x = m_pEffBone->m_matLocal[3][0]; vec3EffPos.y = m_pEffBone->m_matLocal[3][1]; vec3EffPos.z = m_pEffBone->m_matLocal[3][2]; // ワールド座標系から注目ノードの局所(ローカル)座標系への変換 Matrix matInvBone; MatrixInverse( matInvBone, m_ppBoneList[cbLinkIdx]->m_matLocal ); // エフェクタ,到達目標のローカル位置 Vector3Transform( &vec3EffPos, &vec3EffPos, matInvBone ); Vector3Transform( &vec3TargetPos, &vec3OrgTargetPos, matInvBone ); // 十分近ければ終了 Vector3 vec3Diff; Vector3Sub( &vec3Diff, &vec3EffPos, &vec3TargetPos ); if( Vector3DotProduct( &vec3Diff, &vec3Diff ) < 0.0000001f ) return; // (1) 基準関節→エフェクタ位置への方向ベクトル Vector3Normalize( &vec3EffPos, &vec3EffPos ); // (2) 基準関節→目標位置への方向ベクトル Vector3Normalize( &vec3TargetPos, &vec3TargetPos ); // ベクトル (1) を (2) に一致させるための最短回転量(Axis-Angle) // // 回転角 float fRotAngle = acosf( Vector3DotProduct( &vec3EffPos, &vec3TargetPos ) ); if( 0.00000001f < fabsf( fRotAngle ) ) { if( fRotAngle < -m_fFact ) fRotAngle = -m_fFact; else if( m_fFact < fRotAngle ) fRotAngle = m_fFact; // 回転軸 Vector3 vec3RotAxis; Vector3CrossProduct( &vec3RotAxis, &vec3EffPos, &vec3TargetPos ); if( Vector3DotProduct( &vec3RotAxis, &vec3RotAxis ) < 0.0000001f ) continue; Vector3Normalize( &vec3RotAxis, &vec3RotAxis ); // 関節回転量の補正 Vector4 vec4RotQuat; QuaternionCreateAxis( &vec4RotQuat, &vec3RotAxis, fRotAngle ); if( m_ppBoneList[cbLinkIdx]->m_bIKLimitAngle ) limitAngle( &vec4RotQuat, &vec4RotQuat ); QuaternionNormalize( &vec4RotQuat, &vec4RotQuat ); QuaternionMultiply( &m_ppBoneList[cbLinkIdx]->m_vec4Rotation, &m_ppBoneList[cbLinkIdx]->m_vec4Rotation, &vec4RotQuat ); QuaternionNormalize( &m_ppBoneList[cbLinkIdx]->m_vec4Rotation, &m_ppBoneList[cbLinkIdx]->m_vec4Rotation ); for( short i = cbLinkIdx ; i >= 0 ; i-- ){ m_ppBoneList[i]->updateMatrix(); } m_pEffBone->updateMatrix(); } } } }