|
/**
* Metasequoia.as
*
* @see http://snippets.libspark.org/
* @see http://snippets.libspark.org/trac/wiki/rch850/Metasequoia
*
* Copyright (c) 2007-2008 rch850
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.libspark.pv3d {
// Main.mxml の firebug 関数参照用
import mx.core.Application;
import mx.controls.*;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.*;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.net.FileReference;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import org.libspark.pv3d.decoders.TGADecoder;
import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.NumberUV;
import org.papervision3d.core.proto.DisplayObjectContainer3D;
import org.papervision3d.core.proto.GeometryObject3D;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.events.FileLoadEvent;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.materials.BitmapFileMaterial;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import nochump.util.zip.*;
import com.voidelement.images.BMPDecoder;
import org.libspark.pv3d.Metasequoia;
//*******************************************************
// Metasequoia 継承クラス
//*******************************************************
public class Metasequoia_v extends Metasequoia {
public var fRef:FileReference;
public var imageExt:String = "png,jpg,jpeg";
private var texget:BitmapMaterial = null;
private var loader:Loader;
private var bmp_loader:Loader;
private var _ext:String;
private var data_list:Object = new Object();
private var zip_num:int; // zipfile 内の ファイル数
private var bitmap_num:int; // zipfile 内の 画像数
private var zipFile:ZipFile;
private var mqo_temp:Array;
private var mqo_target:ByteArray;
private var bitamp_count:int = 0;
private var zip:ByteArray;
// ファイル参照対象ファイルのデフォルト
private var targetDreft:String = "zipfile";
// *************************************************
// コンストラクタ
// *************************************************
function Metasequoia_v() {
super();
// ファイルリファレンスのイベント登録
frefinit();
}
// *************************************************
// ファイルリファレンスのイベント登録
// *************************************************
private function frefinit():void {
bmp_loader = new Loader();
// 画像( テクスチャの取り出し )
bmp_loader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
var i:int;
var ename:String = ZipEntry(zipFile.entries[bitamp_count]).name;
// data_list は、Object。ファイル名によるプロパティに
// Material(テクスチャ) を保存
data_list[ename] = new BitmapMaterial( e.target.content.bitmapData );
bitmap_num--;
if ( bitmap_num <= 0 ) {
mx.core.Application.application.firebug("メタセコイアロード開始");
buildMetasequoia(mqo_target.readMultiByte(mqo_target.length, charset));
dispatchEvent(new Event(Event.COMPLETE));
}
else {
// 次のテクスチャをロードする
for( i = bitamp_count+1; i < zip_num; i++ ) {
if ( chkExt( ZipEntry(zipFile.entries[i]).name, imageExt ) ) {
// 明示的に ByteArray とする
zip = zipFile.getInput(ZipEntry(zipFile.entries[i]));
bmp_loader.loadBytes(zip);
bitamp_count = i;
break;
}
}
}
});
// ファイルリファレンスの準備
fRef = new FileReference();
fRef.addEventListener(Event.OPEN, function(e:Event):void {} );
fRef.addEventListener(ProgressEvent.PROGRESS, function(e:ProgressEvent):void {} );
// load 完了
fRef.addEventListener(Event.COMPLETE, function(e:Event):void {
mx.core.Application.application.firebug("fref : COMPLETE(load) : "+e.target.name);
// zipfile の場合、画像ファイルの bitmapData を BitmapMaterial
// に変換してファイル名で 配列に保存しておく
if ( chkExt( e.target.name, "zip" ) ) {
var i:int; // ループ用
// 明示的に ByteArray とする
zip = FileReference(e.target).data;
// ZipFile のインスタンスを作成する
zipFile = new ZipFile(zip);
zip_num = zipFile.entries.length;
bitmap_num = 0;
// まず画像ファイル数のカウント
for( i = 0; i < zip_num; i++ ) {
if ( chkExt( ZipEntry(zipFile.entries[i]).name, imageExt ) ) {
bitmap_num++;
}
// メタセコイアの ByteArray
if ( chkExt( ZipEntry(zipFile.entries[i]).name, "mqo" ) ) {
mqo_target = zipFile.getInput(ZipEntry(zipFile.entries[i]));
}
}
// 画像( 最初のテクスチャの取り出し ) : 非同期
for( i = 0; i < zip_num; i++ ) {
if ( chkExt( ZipEntry(zipFile.entries[i]).name, imageExt ) ) {
// 明示的に ByteArray とする
zip = zipFile.getInput(ZipEntry(zipFile.entries[i]));
bmp_loader.loadBytes(zip);
bitamp_count = i;
break;
}
}
}
} );
// キャンセル
fRef.addEventListener(Event.CANCEL, function(e:Event):void {
mx.core.Application.application.firebug("fref : cancel : "+e);
} );
// 選択直後
fRef.addEventListener(Event.SELECT, function(e:Event):void {
mx.core.Application.application.firebug("fref : select : "+e.target.name);
if ( chkExt( e.target.name, _ext ) ) {
FileReference(e.target).load();
}
} );
fRef.addEventListener(IOErrorEvent.IO_ERROR, fRefError );
}
private function fRefError( e:IOErrorEvent ):void {
Alert.show(e.text);
}
// *************************************************
// ●公開メソッド : ロード : zipfile のByteArray
// ※ 未テストです
// *************************************************
public function loadZipfle(byteArray:ByteArray, scale:Number = 1):void {
_scale = scale;
var i:int; // ループ用
// ZipFile のインスタンスを作成する
zipFile = new ZipFile(byteArray);
zip_num = zipFile.entries.length;
bitmap_num = 0;
// まず画像ファイル数のカウント
for( i = 0; i < zip_num; i++ ) {
if ( chkExt( ZipEntry(zipFile.entries[i]).name, imageExt ) ) {
bitmap_num++;
}
// メタセコイアの ByteArray
if ( chkExt( ZipEntry(zipFile.entries[i]).name, "mqo" ) ) {
mqo_target = zipFile.getInput(ZipEntry(zipFile.entries[i]));
}
}
// 画像( 最初のテクスチャの取り出し ) : 非同期
for( i = 0; i < zip_num; i++ ) {
if ( chkExt( ZipEntry(zipFile.entries[i]).name, imageExt ) ) {
// 明示的に ByteArray とする
zip = zipFile.getInput(ZipEntry(zipFile.entries[i]));
bmp_loader.loadBytes(zip);
bitamp_count = i;
break;
}
}
}
// *************************************************
// ●公開メソッド : 参照 : 引数は拡張子リスト
// 例 : browse( "zip" ) または
// browse( "jpeg,jpg,png" )
// *************************************************
public function browse(ext:String,scale:Number = 1):void {
_scale = scale;
_ext = ext;
fRef.browse();
}
// *************************************************
// 拡張子チェック
// *************************************************
private function chkExt( target:String, ext:String ):Boolean {
var lst:Array = ext.split(",");
var test:Array = target.split(".");
if ( test.length == 1 ) {
return false;
}
var str:String = String(test[1]);
str = str.toLocaleUpperCase();
var chk:String;
for( var i:int = 0; i < lst.length; i++ ) {
chk = (lst[i]).toLocaleUpperCase();
if ( str == chk ) {
return true;
}
}
return false;
}
/**
* Material チャンクを読み込み、その最後の行番号を返します。
* エラーが起こった場合は -1 を返します。
*/
//*******************************************************
// データ処理の心臓部
//*******************************************************
protected override function parseMaterialChunk(lines:Array, startLine:int):int {
var l:int = getMaterialChunkLine(lines, startLine);
if (l == -1) {
return -1;
}
// 解析中の行の文字列
var line:String = lines[l];
// マテリアル数を取得
var num:Number = parseInt(line.substr(9));
if (isNaN(num)) {
return -1;
}
++l;
_materialNames = new Array();
// } で閉じているところの行番号
var endLine:int = l + int(num);
// mqo ファイルのあるディレクトリのパス
// var path:String = _filename.slice(0, _filename.lastIndexOf("/") + 1);
for (; l < endLine; ++l) {
var material:MaterialObject3D;
line = lines[l];
// マテリアルの名前を取得
var nameBeginIndex:int = line.indexOf("\"");
var nameEndIndex:int = line.indexOf("\"", nameBeginIndex + 1);
var name:String = line.substring(nameBeginIndex + 1, nameEndIndex);
_materialNames.push(name);
// テクスチャファイル名
var tex:String = getParam(line, "tex");
if (tex) {
// テクスチャファイル名を取り囲む " " を取り除く
tex = tex.substr(1, tex.length - 2);
/*
_materialsToLoad++;
if (tex.toLowerCase().search(/\.tga$/) != -1) {
material = loadTGAMaterial(path + tex);
} else if (tex.toLowerCase().search(/\.bmp$/) != -1) {
material = loadBMPMaterial(path + tex);
} else {
// テクスチャの URL を絶対にして読み込む
material = new BitmapFileMaterial(path + tex);
material.addEventListener(FileLoadEvent.LOAD_COMPLETE, materialLoadCompleteHandler);
material.addEventListener(FileLoadEvent.LOAD_ERROR, materialLoadErrorHandler);
}
// あまり重さが変わらないのでせっかくだからスムージング
*/
material = data_list[tex];
material.smooth = true;
} else {
// 形式 - 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]) * 100;
//trace("rgb = " + r + "," + g + "," + b);
material = new ColorMaterial((r << 16) | (g << 8) | b);
} else {
material = MaterialObject3D.DEFAULT;
}
}
material.doubleSided = this.doubleSided;
material.interactive = this.interactive;
material.name = name;
materials.addMaterial(material, name);
}
return endLine;
}
}
}
| |