1. ホーム
  2. Blog
  3. Papervision3D の平面に外部 swf をロード

Papervision3D の平面に外部 swf をロード

寺井 周平

寺井 周平

技術

pv3dTest.jpg

寺井です。Papervision3D のバージョン 2.0:別名「GreatWhite」を触ってみました。

表題にもあるように、今回は「外部 swf ファイルをロードして、Papervision3D の平面(Plane)上に貼り付ける。」というお題です。

3Dオブジェクトの面に対してムービーを貼り付ける「MovieMaterial」の挙動で少し苦労したのでした。

MovieMaterial の使い方は以下のようになります。

new MovieMaterial( 
                movieAsset:DisplayObject=null, 
                transparent:Boolean=false, 
                animated:Boolean=false, 
                precise:Boolean = false 
);

引数はそれぞれ:

  1. movieAsset: テクスチャとして貼り付けたい DisplayObject(僕のサンプルでは Sprite 型の exStageSpr)
  2. transparent: 透過するかどうか。true, false どっちにしても外部 swf の背景は反映されない。何が透過されるんだろう?今回は研究外。
    追記:この transparent パラメーターについて note.x 様が丁寧&カッコイイサンプルで解説をしてくださっています。
    note.x | [PV3D2.0] materials.MovieMaterial
  3. animated: アニメーションさせるかどうか。今回はロードした swf を再生させたいので true に設定。
  4. precise: Render the bitmap using linear texturing を設定できる。

ということで、第1引数に Sprite インスタンス「exStageSpr(名前は任意)」を渡す。その exStageSpr に外部 swf をロードした loader インスタンスを addChild するという、常識的なアプローチ。

結果からいうと、ロードするスプライト上で、事前に drawRect してロード対象の外部 swf ムービーと同じサイズの矩形を描画しておかないとダメ!!っぽい。空スプライトに loader を addChild していた場合には何も表示されなくてハマりました。

ソースはこんな感じ。Main.as としてドキュメントクラスに設定してください。

/*
同じディレクトリに"external.swf"というSWFファイルがあり、これをロードしてPV3D平面に貼り付けるテスト。
回転を止めたければ handleEnterFrame とかは不要。回転を直接指定してください。
40行目のコメントがミソ

「miscellaneous  [ActionScript 3.0] PaperVision3D 2.0 GreatWhite」
(http://yamasv.blog92.fc2.com/blog-entry-101.html)
様のエントリをベースに作成させていただきました。
*/
package {
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.display.Loader;
  import flash.net.URLRequest;
  
  import org.papervision3d.cameras.FreeCamera3D;
  import org.papervision3d.lights.PointLight3D;
  import org.papervision3d.materials.ColorMaterial;
  import org.papervision3d.materials.MovieMaterial;
  import org.papervision3d.materials.utils.MaterialsList;
  import org.papervision3d.objects.DisplayObject3D;
  import org.papervision3d.objects.primitives.Plane;
  import org.papervision3d.render.BasicRenderEngine;
  import org.papervision3d.scenes.Scene3D;
  import org.papervision3d.view.Viewport3D;

  public class Main extends Sprite
  {
    private var renderer:BasicRenderEngine
    private var scene:Scene3D;
    private var camera:FreeCamera3D;
    private var viewport:Viewport3D;
    private var pointLight:PointLight3D;
    public function Main()
    {
      //テクスチャ用ムービークリップ。
      var exStageSpr:Sprite = new Sprite();
      //外部アセットをロードする前に予め矩形描画等でエリア確保が必要っぽい!!
      //読み込むムービーの背景色と同じ塗りの色にする
      exStageSpr.graphics.beginFill(0xFF3300);
      //読み込むムービーのムービーサイズに合わせる
      exStageSpr.graphics.drawRect(0, 0, 300, 200);
      exStageSpr.graphics.endFill();
      var loader:Loader = new Loader();
      exStageSpr.addChild(loader);
      loader.contentLoaderInfo.addEventListener(Event.INIT, initListener);
      loader.load(new URLRequest("external.swf"));
      
      renderer = new BasicRenderEngine();
      scene = new Scene3D();
      camera = new FreeCamera3D();
      viewport  = new Viewport3D(0, 0, true, false);
      addChild(viewport);
      
      //カメラ設定は外部素材のサイズに応じて調整してください。
      camera.z = -400;
      camera.focus = 100;
      camera.zoom = 2;
      
      //exStageSprをテクスチャに設定する。
      var movieMat:MovieMaterial = new MovieMaterial(exStageSpr, false, true, false);
      movieMat.doubleSided = true; //裏表表示
      //平面を作成
      var plane:Plane = new Plane(movieMat,300,200,5,5);
      scene.addChild(plane);
      stage.addEventListener(Event.ENTER_FRAME, handleEnterFrame);
    }
    
    private function initListener(e:Event):void {
      trace("外部 SWF ロード完了")
    }

    private function handleEnterFrame(e:Event):void
    {
      //カメラ設定は外部素材のサイズに応じて調整してください。
      camera.x=camera.y=camera.z=0;
      camera.yaw(1);
      camera.moveBackward(200);
      renderer.renderScene(scene, camera, viewport);
    }
  }
}

ちなみに本体ムービーは AS3 で、外部 swf は AS2 なのですが、ただ再生させるぐらいなら動くんですね。

トップへ戻る