「Doc:JA/2.6/Manual/Game Engine/Python API/VideoTexture」の版間の差分

提供: wiki
< Doc:JA‎ | 2.6‎ | Manual‎ | Game Engine‎ | Python API
移動先: 案内検索
(Created page with "{{Page/Header|2.5|Doc:JA/2.5/Manual/Game Engine/Python API/Bullet physics|Doc:JA/2.5/Manual/Game Engine/Features}} =The VideoTexture module= <code>VideoTexture</code>モジュ...")
 
(1版 をインポートしました)
 
(相違点なし)

2018年6月29日 (金) 05:47時点における最新版

The VideoTexture module

VideoTextureモジュールを使うと、ゲームの実行中にテクスチャを操作できます。テクスチャに使えるソースはいくつかあります、ビデオファイル、イメージファイル、ビデオキャプチャ、メモリバッファ、カメラレンダー、またはこれらの混合です。ビデオファイルとイメージファイルは、ファイル名の代わりにURLを指定することでインターネットからロードできます。さらに、それらのイメージをGPUに送る前にフィルタを適用し、blue screen、color band、gray、normal mapなどの映像効果をかけることもできます。VideoTextureはイメージやビデオをロードするのにFFmpegを使用しており、FFmpegがサポートしているフォーマットはVideoTextureでもすべてサポートされています。以下はサポートしているフォーマットの一部です。

  • AVI
  • Ogg
  • Xvid
  • Theora
  • dv1394 camera
  • video4linux capture card (this includes many webcams)
  • videoForWindows capture card (this includes many webcams)
  • JPG


動作の仕組み

原理は簡単です。まず、すでに存在しているテクスチャをオブジェクトと名前によって指定し、次に動的コンテントを持ったテクスチャを作成して、二つのテクスチャをGPU内で入れ替えます。ゲームエンジンはテクスチャが交換されたことには気づかず、通常通りにオブジェクトを表示します。それでいて、あなたがテクスチャをコントロールできるようになっているわけです。使用を終えると、新しいテクスチャは削除され、古いテクスチャが復帰します。

このページでは簡単な例を使ってVideoTextureモジュールを解説します。

ゲームの準備

VideoTextureモジュールを使う前に、適切なテクスチャをもったオブジェクトがなくてはいけません。

たとえば、ゲームの中に、本物の番組を流しているテレビを配置したいとします。テレビのオブジェクトを作成し、画面の部分には別個のテクスチャをUVマッピングで適用します。たとえば“tv.png”というテクスチャだとしましょう。このテクスチャの内容はここでは重要ではありませんが、おそらく電源が切れている画面のような、暗いグレーにすると良いでしょう。テレビの電源を入れなければならないとき、ビデオキャプチャカードからの映像を使った動的テクスチャが作成されるようにします。それをtv.pngと入れ替えれば、テレビは本物同様になります。

VideoTextureが入れ替えられるテクスチャの作り方は二通りあります。

  1. 単純なUVテクスチャ。
  2. テクスチャチャンネルを持ったBlenderマテリアル。

VideoTextureはテクスチャのレベルで動作するので、ゲームエンジンがもっている凝ったテクスチャ機能も使えます。GLSL、multi-texture、custom shadersなど。

たとえば、ゲーム内のあるオブジェクトが、一つまたはそれ以上の面に対してマテリアル/イメージを適用されており、そこにビデオを表示したいとします。

最初のステップはTextureオブジェクトの作成です。これは一度だけ実行されるスクリプトで行うことにしましょう。ゲームがスタートした時点では、ビデオはテクスチャを更新しない限り表示されないかもしれません。これについてはあとで触れます。通常、スクリプトはビデオを表示させるオブジェクトに付加します。そうするとオブジェクトの参照を簡単に取得できます。

 import VideoTexture
 
 contr = GameLogic.getCurrentController()
 obj = contr.owner
 
 if not hasattr(GameLogic, 'video'):

video”属性をチェックするのは、テクスチャの作成を一度だけにするためです。

マテリアルの取得

     matID = VideoTexture.materialID(obj, 'IMvideo.png')

VideoTexture.materialID()は便利な関数で、これによりvideo.pngをテクスチャとして使っているマテリアルを取得します。この方法はBlenderマテリアルでもUVテクスチャでも使えます。UVテクスチャの場合は、そのテクスチャが適用されている面に付随する内部的なマテリアルを呼び出します。Blenderマテリアルの場合は、そのテクスチャを第一テクスチャとして使っているマテリアルを呼び出します。

IM”の接頭辞は、探しているのがテクスチャであると示すためのものです。マテリアルの場合は“MA”を先頭につけます。たとえば、このオブジェクト上でVideoMatという名前のマテリアルを探す場合、コードは以下のようになります。

     matID = VideoTexture.materialID(obj, 'MAVideoMat')


テクスチャの作成

VideoTexture.Textureクラスは、動的テクスチャをGPUにロードするTextureオブジェクトを作成します。コンストラクタは必須の引数1つと、オプションの引数3つをとります。

gameObj
ゲームオブジェクト。
materialID
VideoTexture.materialID()で返されるのと同じマテリアルインデックス。0にすると最初のマテリアルになります。
textureID
複数のテクスチャが存在すす場合のテクスチャインデックス。0にすると最初のチャンネルになります。
UVテクスチャの場合はこの値は常に0にします。
textureObj
再使用したいテクスチャを持つTextureオブジェクト。
この引数を使う場合、そのテクスチャ上にはいかなるソースも作成するべきではありません。また、テクスチャを更新する必要もありません。得られるテクスチャはマテリアルにもテクスチャにも使用できます。
     GameLogic.video = VideoTexture.Texture(obj, matID)


テクスチャを永続的にする

以前にオブジェクトに対してGameLogicvideo”属性を割り当てましたが、その理由は、Textureはゲームの実行中に永続的でなければならないからです。ローカル変数はスクリプトの終わりで消去され、同時にGPUテクスチャも消去されます。GameLogicモジュールオブジェクトは永続的にしたいオブジェクトを保存するのに便利なのです。

ソースを作成する

Textureオブジェクトを得ることができましたが、テクスチャのソースがないので、これだけでは何もできません。VideoTextureで使用可能な種類の中から、ソースオブジェクトを作成する必要があります。

VideoFFmpeg
動画。
ビデオファイル、ビデオキャプチャ、ビデオストリーミング
ImageFFmpeg
静止画
イメージファイル、ウェブ上のイメージ
ImageBuff
メモリ上のイメージ
CGI、グラフィックアプリケーション
ImageViewport
ビューポートの全体または一部(つまりアクティブカメラによるレンダリングイメージ)
ImageRender
アクティブでないカメラによるレンダリングイメージ
ImageMix
上記のうちの二つ、またはそれ以上の混合

この例ではソースとしてシンプルなビデオファイルを使います。VideoFFmpegコンストラクタはファイル名を引数に取ります。ファイルの場所についての混乱を避けるため、GameLogic.expandPath()を使ってファイルのフルパスを取得します。ここでビデオファイルは.blendファイルと同じディレクトリにあるとします。

     movie = GameLogic.expandPath('//trailer_400p.ogg')
     GameLogic.video.source = VideoTexture.VideoFFmpeg(movie)

ビデオソースオブジェクトを作ったら、それをTextureオブジェクトのsource属性に割り当てることで、ソースのセットアップと永続化を行います。ソースオブジェクトそのものも永続的になります。

Textureのソースはいつでも変更できます。たとえばゲームの進行中に二つの映像を切り替えたい場合、以下のようにします。

     GameLogic.mySources[0] = VideoTexture.VideoFFmpeg('movie1.avi')
     GameLogic.mySources[1] = VideoTexture.VideoFFmpeg('movie2.avi')

そして実行中に再割り当てします。

     GameLogic.video.source = GameLogic.mySources[movieSel]


ソースのセットアップ

VideoFFmpegソースはムービーの再生をコントロールする属性がいくつかあります。

range
[start,stop] (floats).
ビデオの再生範囲。始めからの秒数で指定します。デフォルトではビデオ全体です。
repeat
(integer).
リピート回数。-1で無制限にリピートします。
framerate
(float).
相対的なフレームレート。1.0より小さくすると遅くなり、大きくすると速くなります。
scale
(bool).
Trueにすると高速なニアレストネイバーアルゴリズムで拡大します。
テクスチャに使うビデオの幅と高さは2の乗数でなければいけません。そうでない場合、指定した方法でスケーリングされます。デフォルトでは正確ですが遅いgluScaleImage()関数を使います。一番良いのは最初からビデオを適切な大きさにしておくことです。そうすれば実行時にはスケーリングの必要がなくなります。
flip
(bool).
Trueにするとイメージは上下に反転されます。
FFmpegからのイメージは常に上限判定している状態なので、この属性はデフォルトでTrueになっています。
filter
ビデオをGPUに送る前にフィルタを適用します。
VideoTextureフィルタオブジェクトのうちのひとつを指定します。デフォルトではイメージは何も変更されずにGPUに送られます。ビデオにアルファチャンネルが存在している場合は、それは自動的にロードされてGPUに送られます。

ここではscale属性をTrueにしましょう。なぜならgluScaleImage()は本当に遅くて、リアルタイムビデオには向いていないからです。ビデオの縦横がもともと2の乗数になっている場合は、この設定は何の影響もありません。

     GameLogic.video.source.scale = True


Play the video

これでビデオを再生する準備ができました。

     GameLogic.video.source.play()

ビデオの再生はバックグラウンドプロセスではありません。テクスチャを更新して初めて再生されます。よって、毎フレーム実行されるスクリプトでTextureオブジェクトのcode>refresh()メソッドを呼び出す必要があります。

 if hasattr(GameLogic, 'video'):
     GameLogic.video.refresh(True)

ビデオソースが停止している場合は、refresh()は何の効果もありません。refresh()の引数は、テクスチャを再計算する必要があるかどうかを指定するフラグです。ビデオ再生の場合は、あきらかにTrueでしょう。

ビデオのステータスをチェックする

ビデオソースクラス(VideoFFMpegなど)はstatusという属性を持っています。ビデオが再生中の場合、この値は2です。停止している場合は3です。よっで今回の例では、

 if GameLogic.video.source.status == 3:
     #ビデオは止まっている

高度なワークフロー

Texture.refresh()メソッドでTrueを指定すると、一度GPUに送られたイメージは次のフレームでは無効化され、ソースから新しくロードされます。このやり方では、Pythonでイメージが使用できなくなるという副作用があります。よってソースのrefresh()メソッドを手動で呼び出すという方法もあります。

高度なワークフローの例は以下のようになります。

  • Pythonでイメージバッファを使う (テクスチャには影響しない):
     GameLogic.video.refresh(False)
     image = GameLogic.video.source.image
     # imageはRGBAピクセルのバイナリ列
     # ... imageを使う
     # 次のフレームのため無効にする
     GameLogic.video.source.refresh()
  • Pythonで使うため、GPUにはダウンロードせずにイメージをソースからロードする:
    # テクスチャのほうのrefreshを呼んでいないことに注意
    # テクスチャオブジェクトを使わずにソースオブジェクトだけを作成することもできます
     image = GameLogic.video.source.image
     # ... imageを使う
     GameLogic.video.source.refresh()
  • もしメッシュに適用されているマテリアルが二つ以上あり、特定のマテリアルのテクスチャを修正したい場合、マテリアルのIDを取得します。
matID=VideoTexture.materialID(gameobj,"MAmat.001")

GLSLマテリアルは2チャンネル以上のテクスチャを持つことができます。テクスチャはテクスチャスロットの順番に応じて特定されます。ここでは2としましょう。

tex=VideoTexture.Texture(gameobj, matID, 2)


デモのダウンロード

デモファイルをダウンロードできます。

高度なデモ

このデモは、同じテクスチャ上で二つのビデオを交互に使うデモンストレーションです。このデモを使うにはelephant dreamの予告編(teaser)のビデオファイルが必要です。他のファイルで置き換えることもできます。

このデモImageMixソースを使ったデモンストレーションです。ImageMixは他のTextureソースを必要とします。たとえばVideoFFmpegImageFFmpegImageRenderなど。これらのソースをsetSource()でセットして、setWeight()でそれぞれの相対的な重みを設定します。重みは0から255で、すべてのソースの重みの合計が255にならなければいけません。ImageMixはすべてのソースを重みに応じて合成します。元になる複数のソースは、すべて同じサイズ(一番近い2の乗数にスケーリングされた後で)でなけれはいけません。そうでない場合、コンソールでPythonのエラーが出ます。