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

このエントリをはてなブックマークに追加このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをLivedoor Clipに追加このエントリをYahoo!ブックマークに追加このエントリをFC2ブックマークに追加このエントリをNifty Clipに追加このエントリをPOOKMARK. Airlinesに追加このエントリをBuzzurl(バザール)に追加このエントリをBuzzurl(バザール)に追加このエントリをChoixに追加このエントリをnewsingに追加このエントリをkwoutに追加
2008年2月5日 火曜日1:56:15

MetasequoiaMaterialの使用

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

package org.libspark.pv3d {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.Graphics;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.utils.Dictionary;
   
    import flash.geom.Point;
    import flash.net.URLRequest;
    import org.papervision3d.materials.BitmapMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.events.FileLoadEvent;
   
    public class MetasequoiaMaterial extends BitmapMaterial{
////////////////////////////////////////////////////////////////////////////////////////
//定数定義
////////////////////////////////////////////////////////////////////////////////////////
        private static const TEX:String = "tex";
        private static const APLANE:String = "aplane";
        private static const BUMP:String = "bump";

////////////////////////////////////////////////////////////////////////////////////////
//メンバ変数定義
////////////////////////////////////////////////////////////////////////////////////////
        /**
        * ロードしたビットマップのキャッシュ
        * ロード待ち中:null
        * ロード済み:BitmapData
        * ロード中:この画像をロードしているローダ
        */

        private static var _loadedBitmaps:Dictionary = new Dictionary();

        /**
        * マップのURLを保持する
        */

        private var _maps:Dictionary;
       
        private var _materialsToLoad:Number;
////////////////////////////////////////////////////////////////////////////////////////
//プロパティ定義
////////////////////////////////////////////////////////////////////////////////////////
        /**
        * 模様マップを変更する
        * @param    texBmp
        */

        public function set tex(map:BitmapData):void {
            this.setMaterialMapData(MetasequoiaMaterial.TEX , map)
        }
       
        /**
        * 模様マップを取得する。
        * ここで取得した模様マップを変更しても、マテリアルは変更されない。
        * マテリアルを変更する場合、texプロパティにマテリアルを設定する必要がある
        * @return
        */

        public function get tex():BitmapData {
            return this.getMaterialMapData(MetasequoiaMaterial.TEX);
        }
        /**
        * 透明マップを変更する
        * @param    map
        */

        public function set aplane(map:BitmapData):void {
            this.setMaterialMapData(MetasequoiaMaterial.APLANE , map)
        }
       
        /**
        * 透明マップを取得する。
        * ここで取得した透明マップを変更しても、マテリアルは変更されない。
        * マテリアルを変更する場合、aplaneプロパティにマテリアルを設定する必要がある
        * @return
        */

        public function get aplane():BitmapData {
            return this.getMaterialMapData(MetasequoiaMaterial.APLANE);
        }

        /**
        * バンプマップを変更する
        * @param    map
        */

        public function set bump(map:BitmapData):void {
            this.setMaterialMapData(MetasequoiaMaterial.BUMP , map)
        }
       
        /**
        * バンプマップを取得する。
        * ここで取得したバンプマップを変更しても、マテリアルは変更されない。
        * マテリアルを変更する場合、bumpプロパティにマテリアルを設定する必要がある
        * @return
        */

        public function get bump():BitmapData {
            return this.getMaterialMapData(MetasequoiaMaterial.BUMP);
        }
       
        /**
        * マップデータを設定する
        * @param    type
        * @return
        */

        private function setMaterialMapData(type:String , map:BitmapData):void {
            this._maps[type] = map;
            if (this._materialsToLoad == 0) {
                this.materialLoadComplete();
            }
        }
       
        /**
        * マップデータを取得する
        * @param    type
        * @return
        */

        private function getMaterialMapData(type:String):BitmapData {
            var map:BitmapData = this._maps[type] as BitmapData;
            if (map != null) {
                return map.clone();
            } else {
                return null;
            }
        }

////////////////////////////////////////////////////////////////////////////////////////
//コンストラクタ
////////////////////////////////////////////////////////////////////////////////////////
        /**
        * 新規Metasequoia用マテリアルを作成
        */

        public function MetasequoiaMaterial() {
            this.init();
        }
       
////////////////////////////////////////////////////////////////////////////////////////
//publicな関数
////////////////////////////////////////////////////////////////////////////////////////
        /**
        * メタセコイア用のマテリアルをロード
        * @param    path メタセコイアのモデルデータのパス
        * @param    line メタセコイアのMaterial チャンク1行分
        */

        public function load(path:String , line:String) :void {
            this.init();

            //色設定
            //形式 - col(1.000 1.000 0.000 1.000)
            var colorstr:String = getParam(line, "col");
            if (colorstr != null) {
                var color:Array = colorstr.match(/\d+\.\d+/g);
                var r:int = parseFloat(color[0]) * 255;
                var g:int = parseFloat(color[1]) * 255;
                var b:int = parseFloat(color[2]) * 255;
                var a:Number = parseFloat(color[3]);
                this.fillColor = ((r <<16) | (g <<8) | b);
                this.fillAlpha = a;
            }
           
            // マテリアルの名前を取得
            var nameBeginIndex:int = line.indexOf("\"");
            var nameEndIndex:int = line.indexOf("\"", nameBeginIndex + 1);
            this.name = line.substring(nameBeginIndex + 1, nameEndIndex);

            //テクスチャ画像のパスを取得
            var tex:String = MetasequoiaMaterial.getParam(line , "tex");
            var aplane:String = MetasequoiaMaterial.getParam(line , "aplane");
            var bump:String = MetasequoiaMaterial.getParam(line , "bump");
           

            //各マップのパスがnullでない場合、キャッシュ探索を行う
            if (tex != null) {
                tex = path + tex;
                this._materialsToLoad++;
                this.getImage(tex , MetasequoiaMaterial.TEX);
            }
            if (aplane != null) {
                aplane = path + aplane;
                this._materialsToLoad++;
                this.getImage(aplane , MetasequoiaMaterial.APLANE);
            }
            if (bump != null) {
                bump = path + bump;
                this._materialsToLoad++;
                this.getImage(bump , MetasequoiaMaterial.BUMP);
            }
           
            if (_materialsToLoad == 0) {
                this.materialLoadComplete();
            }
        }

////////////////////////////////////////////////////////////////////////////////////////
//privateな関数
////////////////////////////////////////////////////////////////////////////////////////
        /**
        * 初期化関数
        * @return
        */

        private function init() :void {
            //テクスチャの初期化
            this.bitmap = null;
            this._materialsToLoad = 0;
            this._maps = new Dictionary();
            this._maps[MetasequoiaMaterial.TEX] = null;
            this._maps[MetasequoiaMaterial.APLANE] = null;
            this._maps[MetasequoiaMaterial.BUMP] = null;
        }
        /**
        * キャッシュから画像を検索する。<br />
        * @param    path 画像パス
        * @param    type 画像をどのマップに使用するか?(TEX , APLANE , BUMP)
        * @return キャッシュに画像がある場合はTrue、無い場合はFalse
        */

        private function getImage(path:String , type:String):Boolean {
            //pathもしくはtypeが設定されてなかったら終了
            if (path == null || type == null) {
                return false;
            }
            //キャッシュ探索
            var cache:BitmapData = MetasequoiaMaterial._loadedBitmaps[path] as BitmapData;
            if (cache == null) {
                //キャッシュが無い
                this._maps[type] = path;
               
                //ロード中?
                var loader:Loader = MetasequoiaMaterial._loadedBitmaps[path] as Loader;
                if (loader == null) {
                    //新しく画像をロードする
                    loader = new Loader();
                    loader.name = path;
                    loader.contentLoaderInfo.addEventListener(Event.COMPLETE , loadImageComplete);
                    loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR , loadError);
                    MetasequoiaMaterial._loadedBitmaps[path] = loader;
                    loader.load(new URLRequest(path));
                } else {
                    //画像をロード中だったので、イベントリスナーに自分を追加
                    loader.contentLoaderInfo.addEventListener(Event.COMPLETE , loadImageComplete);
                    loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR , loadError);
                }
            } else {
                this._materialsToLoad--;
                this[type] = cache;
            }
            return cache != null;
        }

        /**
        * 画像読み込み完了時
        * @param    evt
        * @return
        */

        private function loadImageComplete(evt:Event) : void {
            var loader:Loader = evt.target.loader as Loader;
            var bmp:Bitmap = loader.content as Bitmap;
           
            if (bmp != null ){
                //画像をキャッシュに入れる
                MetasequoiaMaterial._loadedBitmaps[loader.name] = bmp.bitmapData;
                //画像を設定する
                if (this._maps[MetasequoiaMaterial.TEX] == loader.name) {
                    //模様マップ
                    this.tex = bmp.bitmapData;
                } else if (this._maps[MetasequoiaMaterial.APLANE] == loader.name) {
                    //透明マップ
                    this.aplane = bmp.bitmapData;
                } else if (this._maps[MetasequoiaMaterial.BUMP] == loader.name) {
                    //バンプマップ
                    this.bump = bmp.bitmapData;
                }
                //画像ロード完了?
                if(--this._materialsToLoad == 0) {
                    this.materialLoadComplete();
                }
            }
        }
        /**
        * ロード失敗時の処理
        * @param    evt
        */

        private function loadError(evt:Event):void {
            var loader:Loader = evt.target.loader as Loader;
            this._materialsToLoad--;
            if (loader != null) {
                trace("    failed to load image[" + loader.name + "]");
            } else {
                trace("    failed to load image[unknown]");
            }
        }

        /**
        * 全マップの読み込み完了時
        * @return
        */

        private function materialLoadComplete():void {
            //透明マップと模様マップから透明部分アリの模様マップを作成
            var bmpData:BitmapData;
            var t:BitmapData = this.tex;
            var a:BitmapData = this.aplane;
            var b:BitmapData = this.bump;
            if (t != null) {
                bmpData = new BitmapData(t.width , t.height , true, this.fillColor);
                bmpData.draw(t);
            } else {
                if (a != null) {
                    bmpData = new BitmapData(a.width , a.height , true , this.fillColor);
                } else {
                    return;
                }
            }
           
            if (a != null) {
                bmpData.copyChannel(a , a.rect , new Point(0,0) , BitmapDataChannel.RED , BitmapDataChannel.ALPHA);
            }
            this.texture = bmpData;

            var fileEvent:FileLoadEvent = new FileLoadEvent( FileLoadEvent.LOAD_COMPLETE);
            this.dispatchEvent( fileEvent );

        }
       
        /**
        * line内からパラメータを抜き出し、返す。
        * 二重引用符(")で囲まれている場合、二重引用符は削除する
        * @param    line パラメータを探し出す文字列
        * @param    paramName 対象パラメータ名
        * @return 対象パラメータ値
        */

        private static function getParam(line:String, paramName:String):String {
            var pattern:RegExp = new RegExp(".*" + paramName + "\\(\"?(.*?)\"?\\).*" , "g");
            if (pattern.test(line)) {
                var result:String = line.replace(pattern , "$1");
                return result;
            } else {
                return null;
            }
        }
       
    }
   
}

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

  • ページ:
  • 1
  • 2
  • 3

TrackBack URL :

コメントする

HTML convert time: 1.576 sec.