Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

Managed DirectXでビデオをテクスチャとして利用する

C#で動画を3D画像へ投影する簡単な方法

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/03/24 12:00

Managed DirectXには「AudioVideoPlayback」という名前空間があります。今回はこの中にある「Video」クラスを用いて、ビデオデータからテクスチャを取り出し、3Dオブジェクトに表示する方法を解説します。

完成図
完成図

はじめに

 Managed DirectXには、ビデオやオーディオを再生する機能を集めた「AudioVideoPlayback」という名前空間があります。今回はこの中にある「Video」というクラスを利用します。

対象読者

 言語はC#を利用し、.Net Framework 1.1とManaged DirectXについてのプログラミング環境がある読者を想定しています。

 それともう1点、今回はDirect3Dについてはあまり触れません。サンプルのため複雑なことはしていませんが、テクスチャが扱える程度の知識は必要です。Direct3Dについては私のページで説明していますので、分からない点があったときは役に立つかもしれません。

必要な環境

 上記の2つの環境が揃っていれば、他に必要なものはありません。

解説内容

 今回は2段階で説明を行います。まずは「Video」を利用した通常のビデオ再生を行い、その後に3Dへの投影を行います。

1. Videoクラスを利用したVideo再生

前準備

 AudioVideoPlaybackを利用するためにはまず、「Microsoft.DirectX」と「Microsoft.DirectX.AudioVideoPlayback」を参照に追加する必要があります。

コード

 Videoクラスの利用の仕方はきわめて単純です。MCI並です。

  1. ファイルを開く
  2. 再生する

 この2手順で行えます。

using Microsoft.DirectX.AudioVideoPlayback;

Video video_;
video_ =new Video("ファイルネーム");
video_.Owner = コントロールをセットする。
video_.Play();

 このコードの必要なところを埋めるだけでビデオが再生できます。

2. テクスチャとして利用する

前準備

 Direct3Dを利用するので、「Microsoft.DirectX.Direct3D」と「Microsoft.DirectX.Direct3DX」を参照に追加してください。

コード

 全体の流れは次のとおりです。

  1. Direct3Dの初期化
  2. Videoの初期化
  3. Videoのコールバック時に描画を行うように設定する。
  4. 再生開始
  5. 各フレームごとにセットした描画メソッドが呼ばれるので、描画を行う。
初期化のコード(1~4の部分)
/// <summary>
/// Dierct3DとVideoの初期化を行う。
/// </summary>
private void myInialize()
{
    //デバイスの初期化
    PresentParameters pp =new PresentParameters();
    pp.Windowed=true;
    pp.SwapEffect =SwapEffect.Discard;

    try
    {
        //ハードウェア
        device_ =new Device(0,DeviceType.Hardware,this
            ,CreateFlags.SoftwareVertexProcessing,pp);
    }
    catch
    {
        try
        {
            //リファレンスで再挑戦
            device_ =new Device(0,DeviceType.Reference,this
                ,CreateFlags.SoftwareVertexProcessing,pp);
        }
        catch
        {
            MessageBox.Show("Direct3Dの初期化に失敗しました");
            return;
        }
    }

    //頂点作成
    vertexBuffer_ =new VertexBuffer(
        typeof(CustomVertex.PositionTextured),4
        ,device_,0,CustomVertex.PositionTextured.Format,Pool.Managed);

    CustomVertex.PositionTextured []verts =
        new CustomVertex.PositionTextured[4];

    verts[0].Position = new Vector3(-1,-1,0);
    verts[1].Position = new Vector3( 1,-1,0);
    verts[2].Position = new Vector3(-1, 1,0);
    verts[3].Position = new Vector3( 1, 1,0);
    verts[0].Tu=1;verts[0].Tv=1;
    verts[1].Tu=0;verts[1].Tv=1;
    verts[2].Tu=1;verts[2].Tv=0;
    verts[3].Tu=0;verts[3].Tv=0;

    GraphicsStream gs =vertexBuffer_.Lock(0,0,0);

    gs.Write(verts);

    vertexBuffer_.Unlock();

    //ビデオ読み込み
    try
    {
        video_ =new Video(@"I:\test.avi");
    }
    catch
    {
        MessageBox.Show("ビデオファイルがありません");
        return;
    }

    //呼び出してもらうメソッドをセットする。
    video_.TextureReadyToRender +=
        new TextureRenderEventHandler(video__TextureReadyToRender);
    //再生を開始する。
    video_.RenderToTexture(device_);

}

 重要なのは最後の2行です。

 「TextureReadyToRender」はVideoを再生したときにテクスチャが準備できると呼び出されます。よって、これに描画のためのメソッドをくっつければ、ビデオをテクスチャとして利用できます。

 「RenderToTexture」はPlayのテクスチャ版です。テクスチャを渡して欲しいときは、これを使ってビデオをスタートさせます。

描画のコード(5の部分)
/// <summary>
///    Videoからの描画呼び出し
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void video__TextureReadyToRender(
    object sender, TextureRenderEventArgs e)
{
    //テクスチャをセット
    device_.SetTexture(0,e.Texture);

    //ステータスを調整
    device_.RenderState.Lighting = false;
    device_.RenderState.CullMode = Cull.None;
    device_.Transform.World =
        Matrix.RotationY(Environment.TickCount/300f);

    //カメラ設定
    device_.Transform.View = Matrix.LookAtLH(
        new Vector3(0,0,3),new Vector3(0,0,0),new  Vector3(0,1,0));
    device_.Transform.Projection =
        Matrix.PerspectiveLH((float)Math.PI / 4f,1,1,100);

    //クリア
    device_.Clear(ClearFlags.Target,Color.Gray.ToArgb(),1.0f,0);

    //描画開始
    device_.BeginScene();

    device_.SetStreamSource(0,vertexBuffer_,0);
    device_.VertexFormat = CustomVertex.PositionTextured.Format;
    device_.DrawPrimitives(PrimitiveType.TriangleStrip,0,2);

    device_.EndScene();

    device_.Present();

}

 これがVideoから呼び出されるメソッドです。「TextureRenderEventArgs」の中にはテクスチャが入っています。これを使って描画を行えばOKです。

後処理について

 このプログラムは[閉じる]ボタンを押しても終了しない可能性があります。対策として、Formがクローズされたときに次の処理を行いましょう。クローズした時に再生が行われる場合はストップする処理です。

private void Form1_Closed(object sender, System.EventArgs e)
{
    if(video_ !=null)
    {
        video_.Stop();
        video_.Dispose();
    }
    if(device_!=null)
    {
        device_.Dispose();
    }
}

まとめ

 今回はテクスチャをただUVマッピングで貼り付けただけでしたが、ピクセルシェーダーを使ってリアルタイムエフェクトをかけながら動画を再生すると、もっと面白いと思います。

参考資料

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

修正履歴

  • 2006/04/08 14:15 リンク先修正。

著者プロフィール

  • 利都(りと)

    陸奥でプログラムをしている学生。 LOGOからVB6.0へ。 現在は主にC系言語を利用。 Atelier BlueにてManaged DirectXについてのTipsを書いている。 http://www.atelier-blue.com/ IL(CIL,MSIL)もしているのでそちらに興味...

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5