D3DImage チュートリアル ⑦ UIと制御の追加
D3DImageの上に半透明のメニューペインを追加し、自動回転の開始・停止用とワイヤーフレーム表示用のチェックボックスを2つ追加します。
D3DRenderer.h
まず、レンダリング時に自動回転とワイヤーフレームのフラグを渡せるようにします。
VOID Render(bool b_AutoRotation, bool b_WireframeMode);
D3DRenderer.cpp
それを基にレンダーステートを変更するようD3DRenderer.cppを編集します。
VOID Render(bool b_AutoRotation, bool b_WireframeMode)
{
// Clear the backbuffer and the zbuffer
g_pd3dDevice->Clear( 0, NULL,
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_ARGB( 0, 0, 0, 0 ), 1.0f, 0 );
// Begin the scene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
// Setup the world, view, and projection matrices
// SetupMatrices();
if (b_AutoRotation) SetupMatrices();
g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,
(b_WireframeMode) ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,
(b_WireframeMode) ? D3DCULL_NONE : D3DCULL_CCW);
これだけでもよいのですが、もともとの回転が時間を基にしているため、一度回転を止めてから再開すると、ジャンプしてしまうので、SetupMatrices()も少し変更します。
VOID SetupMatrices()
{
// Set up world matrix
D3DXMATRIX matWorld;
// D3DXMatrixRotationY( &matWorld,
timeGetTime() / 1000.0f );
static float angle = 0.0f;
D3DXMatrixRotationY( &matWorld, angle+=0.03f );
D3DWrapper.cpp
ラッパーでは、前述のフラグをパブリック プロパティとして定義し、::Renderメソッド呼び出しの引数とします。
public ref class D3DWrapper
{
private:
bool _rotation;
bool _wireframe;
public:
D3DWrapper()
{
_rotation = true;
_wireframe = false;
}
property bool AutoRotate
{
bool get() {return _rotation;}
void set(bool value) { _rotation = value;}
}
property bool RenderWireframe
{
bool get() {return _wireframe;}
void set(bool value) { _wireframe = value;}
}
...
VOID Render(int% width, int% height)
{
::Render(_rotation, _wireframe);
width = SCREEN_WIDTH;
height = SCREEN_HEIGHT;
}
Window1.xaml
XAMLでは、メニューを追加します。
<StackPanel HorizontalAlignment="Left" Width="100" Margin="5">
<StackPanel.Background>
<SolidColorBrush Color="Black" Opacity="0.3"/>
</StackPanel.Background>
<CheckBox Name="Rot" Margin="5" Content="Rotation"
Foreground="White" Unchecked="RotationChanged"
Checked="RotationChanged" IsChecked="True" />
<CheckBox Name="Wire" Margin="5" Content="Wireframe"
Foreground="White" Unchecked="WireframeChanged"
Checked="WireframeChanged" IsChecked="False" />
</StackPanel>
Window1.xaml.cs
コードビハインドのC#ではコールバックを実装し、前述のフラグをセットします。
private void RotationChanged(object sender, RoutedEventArgs e)
{
CheckBox c = sender as CheckBox;
myD3DScene.AutoRotate = c.IsChecked.Value;
}
private void WireframeChanged(object sender, RoutedEventArgs)
{
CheckBox c = sender as CheckBox;
myD3DScene.RenderWireframe = c.IsChecked.Value;
}
F5キーを押してデバッグ実行してください。以下のようにメニュー付きでトラが回転します。Rotationをオフにすると回転が止まります。Wireframeをオンにするとワイヤーフレームのトラになります。
これら以外にも、マウスでの座標変換などのいろいろな制御も可能でしょう。WPFなので、コントロールテンプレートを変更してもっとかっこいいメニューにすることもできるでしょう。使いやすいUIをWPFで、高速な3DをDirect3Dでという組み合わせは、なかなか便利だと思います。
完成したプロジェクトは「第0回はじめに」にあります。