Shape.cpp
#include "StdAfx.h"
#include "Shape.h"
#include "XFile.h"
using namespace Core;
using namespace Robotics;
using namespace Microsoft;
using namespace System;
using namespace System::Diagnostics;
/// [ Constructor ]
Shape::Shape( Robotics::Size size, Robotics::PositionVector^ relativePosition ) :
m_size( size ),
m_relativePosition( relativePosition )
{
}
/// XMLから生成する [ Constructor ]
Shape::Shape( System::Xml::XmlElement^ element ) :
m_size( 0.0, 0.0, 0.0 )
{
if( element == nullptr )
{
// 要素が存在しないならば、相対位置をゼロで初期化する
m_relativePosition = gcnew PositionVector( 0.0, 0.0, 0.0 );
}
else
{
m_size = Robotics::Size( element ); // 大きさ
m_relativePosition = gcnew PositionVector( element ); // 相対位置
}
}
/// [ Finalizer ]
Shape::!Shape()
{
delete m_simpleFigure;
}
/// 生成する
Shape^ Shape::Create( System::Xml::XmlElement^ element )
{
// 要素を取得する
Xml::XmlElement^ node = element[ "shape" ];
// ... 生成して返す
return gcnew Shape( node );
}
/// 頂点の相対位置を取得する [ Property ]
PositionVectors^ Shape::RelativePositionOfVertices::get()
{
PositionVectors^ result = gcnew PositionVectors( VertexSum );
// 形状の半分の大きさを定義する
Robotics::Size size = m_size / 2.0;
// 下面の4点を生成する
result[ 0 ] = gcnew PositionVector( -size.X, -size.Y, -size.Z );
result[ 1 ] = gcnew PositionVector( -size.X, +size.Y, -size.Z );
result[ 2 ] = gcnew PositionVector( +size.X, +size.Y, -size.Z );
result[ 3 ] = gcnew PositionVector( +size.X, -size.Y, -size.Z );
// 上面の4点を生成する
result[ 4 ] = gcnew PositionVector( -size.X, -size.Y, +size.Z );
result[ 5 ] = gcnew PositionVector( -size.X, +size.Y, +size.Z );
result[ 6 ] = gcnew PositionVector( +size.X, +size.Y, +size.Z );
result[ 7 ] = gcnew PositionVector( +size.X, -size.Y, +size.Z );
// ... 相対位置に補正する
for each( PositionVector^ positionVector in result )
{
positionVector += m_relativePosition;
}
return result;
}
/// 頂点の絶対位置を取得する
PositionVectors^ Shape::GetAbsolutePositionOfVertices( Robotics::Vector^ position, Robotics::RotationMatrix^ posture )
{
PositionVectors^ result = gcnew PositionVectors( VertexSum );
PositionVectors^ relativePositionOfVertices = RelativePositionOfVertices; // 頂点の相対位置
for( int i = 0; i < result->Length; i++ )
{
// 指定された位置に、姿勢と頂点の相対位置の積から求めた位置を加算する
result[ i ] = position + ( posture * relativePositionOfVertices[ i ] );
}
return result;
}
/// インスタンスの説明を文字列で返す
System::String^ Shape::ToString()
{
return m_size.ToString();
}
/// 図形を生成する
void Shape::CreateFigure( Microsoft::DirectX::Direct3D::Device^ device )
{
if( !m_size.IsZero() )
{
// 大きさを持つならば、標準メッシュから図形を生成する
m_simpleFigure = DirectX::Direct3D::Mesh::Box(
device,
safe_cast< float >( m_size.X ),
safe_cast< float >( m_size.Y ),
safe_cast< float >( m_size.Z )
);
}
// 名称と同じファイル名を指定する
String^ fileName = Name + ".x";
// @note 作業フォルダから読み込む。
if( IO::File::Exists( fileName ) )
{
// ファイルが存在するならば、Xファイルから読み込む
m_realFigure = gcnew XFile( device, fileName );
}
}
/// シンプルな形状を描画する
void Shape::RenderSimpleFigure( Microsoft::DirectX::Direct3D::Device^ device )
{
// サイズがあることを確認する
if( !m_size.IsZero() )
{
Debug::Assert( Figure == m_simpleFigure, "識別の図形に設定されている" );
// マテリアルを設定する
SetupMaterial( device );
// ワールド座標を保存する
DirectX::Matrix worldMatrix = device->Transform->World;
// 相対位置に移動する
WorldTransformOfFigure
= DirectX::Matrix::Translation(
safe_cast< float >( m_relativePosition->X ),
safe_cast< float >( m_relativePosition->Y ),
safe_cast< float >( m_relativePosition->Z )
)
* worldMatrix;
// ... それをワールド座標に設定する
device->Transform->World = WorldTransformOfFigure;
// レンダリングする
m_simpleFigure->DrawSubset( 0 );
// ワールド座標を元に戻す
device->Transform->World = worldMatrix;
}
}
/// リアルな形状を描画する
void Shape::RenderRealFigure( Microsoft::DirectX::Direct3D::Device^ device )
{
if( m_realFigure != nullptr )
{
Debug::Assert( Figure == m_realFigure->Mesh, "識別の図形に設定されている" );
// ワールド座標を保存する
WorldTransformOfFigure = device->Transform->World;
// ... 描画する
m_realFigure->Render( device );
}
}
/// 表示モードを設定する
void Shape::SetExpressionMode( ExpressionModel expressionModel )
{
// ピッキングによる認識を有効にするために、識別の図形に設定する
switch( expressionModel )
{
case ExpressionModel::MechanismModel: // 機構モデル
// シンプルな形状を設定する
Figure = m_simpleFigure;
break;
case ExpressionModel::RealModel: // リアル モデル
// リアルな形状を設定する
Figure = ( m_realFigure != nullptr )? m_realFigure->Mesh : nullptr;
break;
default:
Debug::Fail( "無効な表示モードが指定された" );
}
}