Metasequoia改造論(2) 透明マップの読み込み

  • このエントリーをはてなブックマークに追加
  • 0

MetasequoiaMaterialの使用

次に、Metasequoia用のマテリアルを扱う、MetasequoiaMaterialというクラスを準備する。

ActionScript

  1. package org.libspark.pv3d {
  2.     import flash.display.Bitmap;
  3.     import flash.display.BitmapData;
  4.     import flash.display.BitmapDataChannel;
  5.     import flash.display.Graphics;
  6.     import flash.display.Loader;
  7.     import flash.events.Event;
  8.     import flash.events.IOErrorEvent;
  9.     import flash.utils.Dictionary;
  10.    
  11.     import flash.geom.Point;
  12.     import flash.net.URLRequest;
  13.     import org.papervision3d.materials.BitmapMaterial;
  14.     import org.papervision3d.objects.DisplayObject3D;
  15.     import org.papervision3d.events.FileLoadEvent;
  16.    
  17.     public class MetasequoiaMaterial extends BitmapMaterial{
  18. ////////////////////////////////////////////////////////////////////////////////////////
  19. //定数定義
  20. ////////////////////////////////////////////////////////////////////////////////////////
  21.         private static const TEX:String = "tex";
  22.         private static const APLANE:String = "aplane";
  23.         private static const BUMP:String = "bump";
  24.  
  25. ////////////////////////////////////////////////////////////////////////////////////////
  26. //メンバ変数定義
  27. ////////////////////////////////////////////////////////////////////////////////////////
  28.         /**
  29.         * ロードしたビットマップのキャッシュ
  30.         * ロード待ち中:null
  31.         * ロード済み:BitmapData
  32.         * ロード中:この画像をロードしているローダ
  33.         */
  34.         private static var _loadedBitmaps:Dictionary = new Dictionary();
  35.  
  36.         /**
  37.         * マップのURLを保持する
  38.         */
  39.         private var _maps:Dictionary;
  40.        
  41.         private var _materialsToLoad:Number;
  42. ////////////////////////////////////////////////////////////////////////////////////////
  43. //プロパティ定義
  44. ////////////////////////////////////////////////////////////////////////////////////////
  45.         /**
  46.         * 模様マップを変更する
  47.         * @param    texBmp
  48.         */
  49.         public function set tex(map:BitmapData):void {
  50.             this.setMaterialMapData(MetasequoiaMaterial.TEX , map)
  51.         }
  52.        
  53.         /**
  54.         * 模様マップを取得する。
  55.         * ここで取得した模様マップを変更しても、マテリアルは変更されない。
  56.         * マテリアルを変更する場合、texプロパティにマテリアルを設定する必要がある
  57.         * @return
  58.         */
  59.         public function get tex():BitmapData {
  60.             return this.getMaterialMapData(MetasequoiaMaterial.TEX);
  61.         }
  62.         /**
  63.         * 透明マップを変更する
  64.         * @param    map
  65.         */
  66.         public function set aplane(map:BitmapData):void {
  67.             this.setMaterialMapData(MetasequoiaMaterial.APLANE , map)
  68.         }
  69.        
  70.         /**
  71.         * 透明マップを取得する。
  72.         * ここで取得した透明マップを変更しても、マテリアルは変更されない。
  73.         * マテリアルを変更する場合、aplaneプロパティにマテリアルを設定する必要がある
  74.         * @return
  75.         */
  76.         public function get aplane():BitmapData {
  77.             return this.getMaterialMapData(MetasequoiaMaterial.APLANE);
  78.         }
  79.  
  80.         /**
  81.         * バンプマップを変更する
  82.         * @param    map
  83.         */
  84.         public function set bump(map:BitmapData):void {
  85.             this.setMaterialMapData(MetasequoiaMaterial.BUMP , map)
  86.         }
  87.        
  88.         /**
  89.         * バンプマップを取得する。
  90.         * ここで取得したバンプマップを変更しても、マテリアルは変更されない。
  91.         * マテリアルを変更する場合、bumpプロパティにマテリアルを設定する必要がある
  92.         * @return
  93.         */
  94.         public function get bump():BitmapData {
  95.             return this.getMaterialMapData(MetasequoiaMaterial.BUMP);
  96.         }
  97.        
  98.         /**
  99.         * マップデータを設定する
  100.         * @param    type
  101.         * @return
  102.         */
  103.         private function setMaterialMapData(type:String , map:BitmapData):void {
  104.             this._maps[type] = map;
  105.             if (this._materialsToLoad == 0) {
  106.                 this.materialLoadComplete();
  107.             }
  108.         }
  109.        
  110.         /**
  111.         * マップデータを取得する
  112.         * @param    type
  113.         * @return
  114.         */
  115.         private function getMaterialMapData(type:String):BitmapData {
  116.             var map:BitmapData = this._maps[type] as BitmapData;
  117.             if (map != null) {
  118.                 return map.clone();
  119.             } else {
  120.                 return null;
  121.             }
  122.         }
  123.  
  124. ////////////////////////////////////////////////////////////////////////////////////////
  125. //コンストラクタ
  126. ////////////////////////////////////////////////////////////////////////////////////////
  127.         /**
  128.         * 新規Metasequoia用マテリアルを作成
  129.         */
  130.         public function MetasequoiaMaterial() {
  131.             this.init();
  132.         }
  133.        
  134. ////////////////////////////////////////////////////////////////////////////////////////
  135. //publicな関数
  136. ////////////////////////////////////////////////////////////////////////////////////////
  137.         /**
  138.         * メタセコイア用のマテリアルをロード
  139.         * @param    path メタセコイアのモデルデータのパス
  140.         * @param    line メタセコイアのMaterial チャンク1行分
  141.         */
  142.         public function load(path:String , line:String) :void {
  143.             this.init();
  144.  
  145.             //色設定
  146.             //形式 - col(1.000 1.000 0.000 1.000)
  147.             var colorstr:String = getParam(line, "col");
  148.             if (colorstr != null) {
  149.                 var color:Array = colorstr.match(/\d+\.\d+/g);
  150.                 var r:int = parseFloat(color[0]) * 255;
  151.                 var g:int = parseFloat(color[1]) * 255;
  152.                 var b:int = parseFloat(color[2]) * 255;
  153.                 var a:Number = parseFloat(color[3]);
  154.                 this.fillColor = ((r < < 16) | (g << 8) | b);
  155.                 this.fillAlpha = a;
  156.             }
  157.            
  158.             // マテリアルの名前を取得
  159.             var nameBeginIndex:int = line.indexOf("\"");
  160.             var nameEndIndex:int = line.indexOf("\"", nameBeginIndex + 1);
  161.             this.name = line.substring(nameBeginIndex + 1, nameEndIndex);
  162.  
  163.             //テクスチャ画像のパスを取得
  164.             var tex:String = MetasequoiaMaterial.getParam(line , "tex");
  165.             var aplane:String = MetasequoiaMaterial.getParam(line , "aplane");
  166.             var bump:String = MetasequoiaMaterial.getParam(line , "bump");
  167.            
  168.  
  169.             //各マップのパスがnullでない場合、キャッシュ探索を行う
  170.             if (tex != null) {
  171.                 tex = path + tex;
  172.                 this._materialsToLoad++;
  173.                 this.getImage(tex , MetasequoiaMaterial.TEX);
  174.             }
  175.             if (aplane != null) {
  176.                 aplane = path + aplane;
  177.                 this._materialsToLoad++;
  178.                 this.getImage(aplane , MetasequoiaMaterial.APLANE);
  179.             }
  180.             if (bump != null) {
  181.                 bump = path + bump;
  182.                 this._materialsToLoad++;
  183.                 this.getImage(bump , MetasequoiaMaterial.BUMP);
  184.             }
  185.            
  186.             if (_materialsToLoad == 0) {
  187.                 this.materialLoadComplete();
  188.             }
  189.         }
  190.  
  191. ////////////////////////////////////////////////////////////////////////////////////////
  192. //privateな関数
  193. ////////////////////////////////////////////////////////////////////////////////////////
  194.         /**
  195.         * 初期化関数
  196.         * @return
  197.         */
  198.         private function init() :void {
  199.             //テクスチャの初期化
  200.             this.bitmap = null;
  201.             this._materialsToLoad = 0;
  202.             this._maps = new Dictionary();
  203.             this._maps&#91;MetasequoiaMaterial.TEX] = null;
  204.             this._maps&#91;MetasequoiaMaterial.APLANE] = null;
  205.             this._maps&#91;MetasequoiaMaterial.BUMP] = null;
  206.         }
  207.         /**
  208.         * キャッシュから画像を検索する。<br />
  209.         * @param    path 画像パス
  210.         * @param    type 画像をどのマップに使用するか?(TEX , APLANE , BUMP)
  211.         * @return キャッシュに画像がある場合はTrue、無い場合はFalse
  212.         */
  213.         private function getImage(path:String , type:String):Boolean {
  214.             //pathもしくはtypeが設定されてなかったら終了
  215.             if (path == null || type == null) {
  216.                 return false;
  217.             }
  218.             //キャッシュ探索
  219.             var cache:BitmapData = MetasequoiaMaterial._loadedBitmaps[path] as BitmapData;
  220.             if (cache == null) {
  221.                 //キャッシュが無い
  222.                 this._maps[type] = path;
  223.                
  224.                 //ロード中?
  225.                 var loader:Loader = MetasequoiaMaterial._loadedBitmaps[path] as Loader;
  226.                 if (loader == null) {
  227.                     //新しく画像をロードする
  228.                     loader = new Loader();
  229.                     loader.name = path;
  230.                     loader.contentLoaderInfo.addEventListener(Event.COMPLETE , loadImageComplete);
  231.                     loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR , loadError);
  232.                     MetasequoiaMaterial._loadedBitmaps[path] = loader;
  233.                     loader.load(new URLRequest(path));
  234.                 } else {
  235.                     //画像をロード中だったので、イベントリスナーに自分を追加
  236.                     loader.contentLoaderInfo.addEventListener(Event.COMPLETE , loadImageComplete);
  237.                     loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR , loadError);
  238.                 }
  239.             } else {
  240.                 this._materialsToLoad--;
  241.                 this[type] = cache;
  242.             }
  243.             return cache != null;
  244.         }
  245.  
  246.         /**
  247.         * 画像読み込み完了時
  248.         * @param    evt
  249.         * @return
  250.         */
  251.         private function loadImageComplete(evt:Event) : void {
  252.             var loader:Loader = evt.target.loader as Loader;
  253.             var bmp:Bitmap = loader.content as Bitmap;
  254.            
  255.             if (bmp != null ){
  256.                 //画像をキャッシュに入れる
  257.                 MetasequoiaMaterial._loadedBitmaps[loader.name] = bmp.bitmapData;
  258.                 //画像を設定する
  259.                 if (this._maps[MetasequoiaMaterial.TEX] == loader.name) {
  260.                     //模様マップ
  261.                     this.tex = bmp.bitmapData;
  262.                 } else if (this._maps[MetasequoiaMaterial.APLANE] == loader.name) {
  263.                     //透明マップ
  264.                     this.aplane = bmp.bitmapData;
  265.                 } else if (this._maps[MetasequoiaMaterial.BUMP] == loader.name) {
  266.                     //バンプマップ
  267.                     this.bump = bmp.bitmapData;
  268.                 }
  269.                 //画像ロード完了?
  270.                 if(--this._materialsToLoad == 0) {
  271.                     this.materialLoadComplete();
  272.                 }
  273.             }
  274.         }
  275.         /**
  276.         * ロード失敗時の処理
  277.         * @param    evt
  278.         */
  279.         private function loadError(evt:Event):void {
  280.             var loader:Loader = evt.target.loader as Loader;
  281.             this._materialsToLoad--;
  282.             if (loader != null) {
  283.                 trace("    failed to load image[" + loader.name + "]");
  284.             } else {
  285.                 trace("    failed to load image[unknown]");
  286.             }
  287.         }
  288.  
  289.         /**
  290.         * 全マップの読み込み完了時
  291.         * @return
  292.         */
  293.         private function materialLoadComplete():void {
  294.             //透明マップと模様マップから透明部分アリの模様マップを作成
  295.             var bmpData:BitmapData;
  296.             var t:BitmapData = this.tex;
  297.             var a:BitmapData = this.aplane;
  298.             var b:BitmapData = this.bump;
  299.             if (t != null) {
  300.                 bmpData = new BitmapData(t.width , t.height , true, this.fillColor);
  301.                 bmpData.draw(t);
  302.             } else {
  303.                 if (a != null) {
  304.                     bmpData = new BitmapData(a.width , a.height , true , this.fillColor);
  305.                 } else {
  306.                     return;
  307.                 }
  308.             }
  309.            
  310.             if (a != null) {
  311.                 bmpData.copyChannel(a , a.rect , new Point(0,0) , BitmapDataChannel.RED , BitmapDataChannel.ALPHA);
  312.             }
  313.             this.texture = bmpData;
  314.  
  315.             var fileEvent:FileLoadEvent = new FileLoadEvent( FileLoadEvent.LOAD_COMPLETE);
  316.             this.dispatchEvent( fileEvent );
  317.  
  318.         }
  319.        
  320.         /**
  321.         * line内からパラメータを抜き出し、返す。
  322.         * 二重引用符(")で囲まれている場合、二重引用符は削除する
  323.         * @param    line パラメータを探し出す文字列
  324.         * @param    paramName 対象パラメータ名
  325.         * @return 対象パラメータ値
  326.         */
  327.         private static function getParam(line:String, paramName:String):String {
  328.             var pattern:RegExp = new RegExp(".*" + paramName + "\\(\"?(.*?)\"?\\).*" , "g");
  329.             if (pattern.test(line)) {
  330.                 var result:String = line.replace(pattern , "$1");
  331.                 return result;
  332.             } else {
  333.                 return null;
  334.             }
  335.         }
  336.        
  337.     }
  338.    
  339. }

このクラスは、模様マップと透明マップのロードを行い、完了後に合成して透明部分を持ったBitmapDataを作成する。また、ロードした画像をキャッシュしたりする機能を持っている。

スポンサーリンク
スポンサーリンク
  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
スポンサーリンク