Joint.cpp
#include "StdAfx.h"
#include "Joint.h"
using namespace Core;
using namespace Robotics;
using namespace Microsoft;
using namespace System;
using namespace System::Diagnostics;
// DirectXのライブラリによる const/volatile 修飾子の使用の警告を抑制する
#pragma warning( disable : 4400 )
/// [ Constructor ]
Joint::Joint( Robotics::PositionVector^ relativePosition, Robotics::AxisVector^ axialDirection, Robotics::Angle angle ) :
m_relativePosition( relativePosition ),
m_axialDirection( axialDirection ),
m_angle( angle ),
m_initialAngle( angle )
{
m_absolutePosition = gcnew PositionVector();
// 位置ベクトルの 値の変更イベントに登録する
m_relativePosition->ValueChanged += gcnew System::EventHandler( this, &Joint::OnMechanicsChanged );
}
/// 絶対位置を設定する [ Property ]
void Joint::AbsolutePosition::set( PositionVector^ value )
{
if( m_absolutePosition != value )
{
// 現在の値と異なるならば、設定する
m_absolutePosition = value;
// ... 絶対位置の変更イベントを発生する
AbsolutePositionChanged( this, nullptr );
}
}
/// 回転角を設定する [ Property ]
void Joint::Angle::set( Robotics::Angle value )
{
Debug::Assert( m_angleRange.IsWithinRange( value ), "指定値は範囲内である" );
if( m_angle != value )
{
// 現在の値と異なるならば、設定する
m_angle = value;
// ... 角度の変更イベントを発生する
AngleChanged( this, nullptr );
}
}
/// 範囲内で回転角に加算する
void Joint::AddAngleWithinRange( double value )
{
double newValue = m_angle + value;
// 回転角の範囲内に収まるように修正する
newValue = Math::Max( newValue, m_angleRange.Minimum );
newValue = Math::Min( newValue, m_angleRange.Maximum );
this->Angle = Robotics::Angle( newValue ); // 回転角
}
/// 回転角を初期化する
void Joint::InitializeAngle()
{
this->Angle = m_initialAngle;
}
/// 構造変化イベントを発生する
void Joint::OnMechanicsChanged( System::Object^, System::EventArgs^ e )
{
MechanicsChanged( this, e );
}
/// インスタンスの説明を文字列で返す
System::String^ Joint::ToString()
{
return this->Name;
}
/// 図形を生成する
void Joint::CreateFigure( Microsoft::DirectX::Direct3D::Device^ device )
{
// 標準メッシュから図形を生成する
Figure = DirectX::Direct3D::Mesh::Cylinder(
device,
0.007f, // Z軸の負の方向に向いている面の円の半径[ m ]
0.007f, // Z軸の正の方向に向いている面の円の半径[ m ]
0.025f, // 円柱の長さ[ m ]
8, // 円以外の棒の部分にあたる Z 軸に平行な分割数
1 // 円以外の棒の部分にあたる Z 軸に垂直な分割数
);
}
/// 描画する
void Joint::Render( Microsoft::DirectX::Direct3D::Device^ device )
{
Debug::Assert( m_axialDirection != nullptr, "軸方向は定義されている" );
// マテリアルを設定する
SetupMaterial( device );
// ワールド座標を保存する
DirectX::Matrix worldMatrix = device->Transform->World;
// 回転角を求める
double rotationY = Math::Atan2( m_axialDirection->X, m_axialDirection->Z );
double rotationX = Math::Atan2( m_axialDirection->Y, m_axialDirection->Z );
// 回転軸の方向へ回転するための ワールド変換行列を求める
WorldTransformOfFigure
= DirectX::Matrix::RotationY( safe_cast< float >( rotationY ) )
* DirectX::Matrix::RotationX( safe_cast< float >( rotationX ) )
* worldMatrix;
// ... それをワールド座標に設定する
device->Transform->World = WorldTransformOfFigure;
/// @note
/// 初期状態でZ軸方向を向いているため、X軸とY軸回りに回転させるだけでよい。
// レンダリングする
Figure->DrawSubset( 0 );
// ワールド座標を元に戻す
device->Transform->World = worldMatrix;
}
/// 軸周りに回転する
void Joint::RotateAroundAxis( Microsoft::DirectX::Direct3D::Device^ device )
{
Debug::Assert( m_axialDirection != nullptr, "軸方向は定義されている" );
// 軸方向から 回転軸を生成する
DirectX::Vector3 axis = DirectX::Vector3(
safe_cast< float >( m_axialDirection->X ),
safe_cast< float >( m_axialDirection->Y ),
safe_cast< float >( m_axialDirection->Z )
);
// ... 軸方向を中心に ワールド座標を回転する
device->Transform->World
= DirectX::Matrix::RotationAxis( axis, safe_cast< float >( m_angle ) )
* device->Transform->World;
}