Compartilhar via


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をオンにするとワイヤーフレームのトラになります。

image

これら以外にも、マウスでの座標変換などのいろいろな制御も可能でしょう。WPFなので、コントロールテンプレートを変更してもっとかっこいいメニューにすることもできるでしょう。使いやすいUIをWPFで、高速な3DをDirect3Dでという組み合わせは、なかなか便利だと思います。

完成したプロジェクトは「第0回はじめに」にあります。