/**
* Copyright h_sakurai ( http://wonderfl.net/user/h_sakurai )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/b80h
*/
package {
import org.papervision3d.view.*;
//import org.libspark.pv3d.Metasequoia;
import flash.text.*;
public class MetasequoiaTest extends BasicView{
//兵士モデル
private var soldier:Metasequoia= new Metasequoia();
public function MetasequoiaTest(){
//メタセコイアクラスの生成
addChild(tf);
//mqoファイルの読込み
// soldier.load("heisi.mqo", 1);
soldier.loadText(xml+"");
soldier.y = -150;
//シーンに追加
scene.addChild(soldier);
//カメラの設定
camera.x = 0;
camera.y = 0;
camera.z =-2000;
camera.focus = 100; //focus×zoom分、オブジェクトから離れている場合
camera.zoom = 10; //画面に同じ大きさで描画される
//描画開始
startRendering();
}
}
}
var xml:XML=(<root><![CDATA[Metasequoia Document
Format Text Ver 1.0
Scene {
pos -26.7442 -27.9070 1500.0000
lookat 0.0000 0.0000 0.0000
head -20.3037
pich 0.8308
ortho 0
zoom2 2.7397
amb 0.250 0.250 0.250
}
Material 1 {
"mat1" col(1.000 0.125 0.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00)
}
Object "obj1" {
visible 15
locking 0
shading 0
facet 59.5
color 0.898 0.498 0.698
color_type 0
vertex 42 {
-0.0001 100.0000 0.0000
-0.0001 92.3879 66.5691
27.0598 92.3879 47.0715
38.2683 92.3879 0.0000
-38.2683 92.3879 0.0000
-27.0598 92.3879 47.0715
-0.0001 70.7107 123.0037
49.9999 70.7107 86.9767
70.7106 70.7107 0.0000
-70.7108 70.7107 0.0000
-50.0000 70.7107 86.9767
-0.0001 38.2683 160.7121
65.3280 38.2683 113.6406
92.3878 38.2683 0.0000
-92.3879 38.2683 0.0000
-65.3283 38.2683 113.6405
-0.0001 0.0000 173.9534
70.7106 0.0000 123.0037
99.9999 0.0000 0.0000
-100.0000 0.0000 0.0000
-70.7108 0.0000 123.0037
-0.0001 100.0000 0.0000
-0.0001 92.3879 66.5691
27.0598 92.3879 47.0715
38.2683 92.3879 0.0000
-38.2683 92.3879 0.0000
-27.0598 92.3879 47.0715
-0.0001 70.7107 123.0037
49.9999 70.7107 86.9767
70.7106 70.7107 0.0000
-70.7108 70.7107 0.0000
-50.0000 70.7107 86.9767
-0.0001 38.2683 160.7121
65.3280 38.2683 113.6406
92.3878 38.2683 0.0000
-92.3879 38.2683 0.0000
-65.3283 38.2683 113.6405
-0.0001 0.0000 173.9534
70.7106 0.0000 123.0037
99.9999 0.0000 0.0000
-100.0000 0.0000 0.0000
-70.7108 0.0000 123.0037
}
face 38 {
3 V(0 2 1) M(0) UV(0.06250 0.00000 0.12500 0.12500 0.00000 0.12500)
3 V(0 3 2) M(0) UV(0.18750 0.00000 0.25000 0.12500 0.12500 0.12500)
3 V(0 5 4) M(0) UV(0.81250 0.00000 0.87500 0.12500 0.75000 0.12500)
3 V(0 1 5) M(0) UV(0.93750 0.00000 1.00000 0.12500 0.87500 0.12500)
4 V(1 2 7 6) M(0) UV(0.00000 0.12500 0.12500 0.12500 0.12500 0.25000 0.00000 0.25000)
4 V(2 3 8 7) M(0) UV(0.12500 0.12500 0.25000 0.12500 0.25000 0.25000 0.12500 0.25000)
4 V(4 5 10 9) M(0) UV(0.75000 0.12500 0.87500 0.12500 0.87500 0.25000 0.75000 0.25000)
4 V(5 1 6 10) M(0) UV(0.87500 0.12500 1.00000 0.12500 1.00000 0.25000 0.87500 0.25000)
4 V(6 7 12 11) M(0) UV(0.00000 0.25000 0.12500 0.25000 0.12500 0.37500 0.00000 0.37500)
4 V(7 8 13 12) M(0) UV(0.12500 0.25000 0.25000 0.25000 0.25000 0.37500 0.12500 0.37500)
4 V(9 10 15 14) M(0) UV(0.75000 0.25000 0.87500 0.25000 0.87500 0.37500 0.75000 0.37500)
4 V(10 6 11 15) M(0) UV(0.87500 0.25000 1.00000 0.25000 1.00000 0.37500 0.87500 0.37500)
4 V(11 12 17 16) M(0) UV(0.00000 0.37500 0.12500 0.37500 0.12500 0.50000 0.00000 0.50000)
4 V(12 13 18 17) M(0) UV(0.12500 0.37500 0.25000 0.37500 0.25000 0.50000 0.12500 0.50000)
4 V(14 15 20 19) M(0) UV(0.75000 0.37500 0.87500 0.37500 0.87500 0.50000 0.75000 0.50000)
4 V(15 11 16 20) M(0) UV(0.87500 0.37500 1.00000 0.37500 1.00000 0.50000 0.87500 0.50000)
3 V(21 23 22) M(0) UV(0.06250 0.00000 0.12500 0.12500 0.00000 0.12500)
3 V(21 24 23) M(0) UV(0.18750 0.00000 0.25000 0.12500 0.12500 0.12500)
3 V(21 26 25) M(0) UV(0.81250 0.00000 0.87500 0.12500 0.75000 0.12500)
3 V(21 22 26) M(0) UV(0.93750 0.00000 1.00000 0.12500 0.87500 0.12500)
4 V(22 23 28 27) M(0) UV(0.00000 0.12500 0.12500 0.12500 0.12500 0.25000 0.00000 0.25000)
4 V(23 24 29 28) M(0) UV(0.12500 0.12500 0.25000 0.12500 0.25000 0.25000 0.12500 0.25000)
4 V(25 26 31 30) M(0) UV(0.75000 0.12500 0.87500 0.12500 0.87500 0.25000 0.75000 0.25000)
4 V(26 22 27 31) M(0) UV(0.87500 0.12500 1.00000 0.12500 1.00000 0.25000 0.87500 0.25000)
4 V(27 28 33 32) M(0) UV(0.00000 0.25000 0.12500 0.25000 0.12500 0.37500 0.00000 0.37500)
4 V(28 29 34 33) M(0) UV(0.12500 0.25000 0.25000 0.25000 0.25000 0.37500 0.12500 0.37500)
4 V(30 31 36 35) M(0) UV(0.75000 0.25000 0.87500 0.25000 0.87500 0.37500 0.75000 0.37500)
4 V(31 27 32 36) M(0) UV(0.87500 0.25000 1.00000 0.25000 1.00000 0.37500 0.87500 0.37500)
4 V(32 33 38 37) M(0) UV(0.00000 0.37500 0.12500 0.37500 0.12500 0.50000 0.00000 0.50000)
4 V(33 34 39 38) M(0) UV(0.12500 0.37500 0.25000 0.37500 0.25000 0.50000 0.12500 0.50000)
4 V(35 36 41 40) M(0) UV(0.75000 0.37500 0.87500 0.37500 0.87500 0.50000 0.75000 0.50000)
4 V(36 32 37 41) M(0) UV(0.87500 0.37500 1.00000 0.37500 1.00000 0.50000 0.87500 0.50000)
4 V(18 19 20 17) M(0) UV(0.25000 0.50000 0.75000 0.50000 0.87500 0.50000 0.12500 0.50000)
3 V(3 21 4) M(0) UV(0.25000 0.12500 0.81250 0.00000 0.75000 0.12500)
4 V(3 4 9 8) M(0) UV(0.25000 0.12500 0.75000 0.12500 0.75000 0.25000 0.25000 0.25000)
4 V(8 9 14 13) M(0) UV(0.25000 0.25000 0.75000 0.25000 0.75000 0.37500 0.25000 0.37500)
4 V(13 14 19 18) M(0) UV(0.25000 0.37500 0.75000 0.37500 0.75000 0.50000 0.25000 0.50000)
3 V(16 17 20) M(0) UV(0.00000 0.50000 0.12500 0.50000 0.87500 0.50000)
}
}
Eof
]]></root>);
import flash.text.*;
var tf:TextField = new TextField();
/**
* 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 {
import flash.display.BitmapData;
import flash.events.*;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
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 com.voidelement.images.BMPDecoder;
/**
* メタセコイアのファイル(.mqo)を読み込むためのクラス。
*
* var mqo = new Metasequoia();
* mqo.addEventListener(...);
* mqo.load("hoge.mqo");
*/
class Metasequoia extends TriangleMesh3D {
/**
* コンストラクタ
*/
function Metasequoia() {
this.materials = new MaterialsList();
super(null, new Array(), new Array(), null);
}
/**
* @param file 読み込むファイルの URL。絶対パスで指定してください。
* @param scale 読み込むときの拡大率。1 が原寸大です。
*/
public function load(file:String, scale:Number = 1):void {
_filename = file;
_scale = scale;
loadMetasequoia();
}
public function loadXML(xml:XML):void {
loadText(xml.text)
}
/**
* ファイルの文字コード。よほどのことが無い限り shift_jis だと思います。
*/
public var charset:String = "shift_jis";
/**
* 面の両側にマテリアルを貼るかどうかを指定します。
*/
public var doubleSided:Boolean = false;
/**
* インタラクティビティを設定します。
*/
public var interactive:Boolean = false;
private var _loader:URLLoader;
private var _filename:String;
private var _materialsToLoad:int =0;
private var _materialNames:Array;
private var _scale:Number = 1;
private var _prevMesh:DisplayObject3D;
private var _prevDepth:int;
private function loadMetasequoia():void {
_loader = new URLLoader();
_loader.dataFormat = URLLoaderDataFormat.BINARY;
_loader.addEventListener(Event.COMPLETE, completeHandler);
_loader.addEventListener(IOErrorEvent.IO_ERROR, defaultHandler);
_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, defaultHandler);
_loader.addEventListener(ProgressEvent.PROGRESS, defaultHandler);
_loader.load(new URLRequest(_filename));
}
private function completeHandler(evt:Event):void {
var byteArray:ByteArray = ByteArray(_loader.data);
loadText(byteArray.readMultiByte(byteArray.length, charset));
dispatchEvent(evt.clone());
}
private function defaultHandler(evt:Event):void {
dispatchEvent(evt.clone());
}
public function loadText(plainText:String):void {
_filename = "./a.moq";
loadText1(plainText);
}
public function loadText1(plainText:String):void {
var lines:Array = plainText.split("\n");
var l:int = 0;
// Material チャンクを読み込む
l = parseMaterialChunk(lines, 0);
_prevDepth = 0;
_prevMesh = this;
// Object チャンクを読み込めなくなるまで読み込む
while (l != -1) {
l = parseObjectChunk(lines, l);
}
geometry.ready = true;
}
/**
* Material チャンクの開始行を返します。
* 見つからなかった場合には -1 を返します。
*/
private function getMaterialChunkLine(lines:Array, startLine:int = 0):int {
for (var i:uint = startLine; i < lines.length; ++i) {
if (lines[i].indexOf("Material") == 0) {
return int(i);
}
}
return -1;
}
/**
* Material チャンクを読み込み、その最後の行番号を返します。
* エラーが起こった場合は -1 を返します。
*/
private 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.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;
}
/**
* Creates a BitmapMaterial from TGA file and returns it.
*/
private function loadTGAMaterial(url:String):BitmapMaterial {
var material:BitmapMaterial = new BitmapMaterial();
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, function(event:Event):void {
var tga:TGADecoder = new TGADecoder(loader.data);
material.bitmap = tga.bitmap;
material.maxU = material.maxV = 1;
material.resetMapping();
});
loader.load(new URLRequest(url));
return material;
}
private function loadBMPMaterial(url:String):BitmapMaterial
{
var material:BitmapMaterial = new BitmapMaterial();
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, function(event:Event):void {
var bmpLoader:URLLoader = event.target as URLLoader;
var decoder:BMPDecoder = new BMPDecoder();
material.bitmap = decoder.decode(bmpLoader.data);
material.maxU = material.maxV = 1;
material.resetMapping();
});
loader.load(new URLRequest(url));
return material;
}
private function materialLoadCompleteHandler(evt:FileLoadEvent):void {
_materialsToLoad--;
if(_materialsToLoad == 0){
//COLLADA のソースにあった謎の一行。不具合の元になるのでコメントアウト
//materials = new MaterialsList();
dispatchEvent(new FileLoadEvent(FileLoadEvent.COLLADA_MATERIALS_DONE));
}
}
private function materialLoadErrorHandler(evt:FileLoadEvent):void {
_materialsToLoad--;
if(_materialsToLoad == 0){
dispatchEvent(new FileLoadEvent(FileLoadEvent.COLLADA_MATERIALS_DONE));
}
}
/**
* Object チャンクの開始行を返します。
* 見つからなかった場合には -1 を返します。
*/
private function getObjectChunkLine(lines:Array, startLine:int = 0):int {
for (var i:uint = startLine; i < lines.length; ++i) {
if (lines[i].indexOf("Object") == 0) {
return int(i);
}
}
return -1;
}
/**
* Object チャンクを読み込み、その最後の行番号を返します。
* エラーが起こった場合は -1 を返します。
*/
private function parseObjectChunk(lines:Array, startLine:int):int {
var l:int = getObjectChunkLine(lines, startLine);
if (l == -1) {
return -1;
}
// 解析中の行の文字列
var line:String = lines[l];
// オブジェクト名を取得
var objectName:String = line.substring(8, line.indexOf("\"", 8));
++l;
var mesh:TriangleMesh3D = new TriangleMesh3D(null, new Array(), new Array(), objectName);
var vertices:Array = mesh.geometry.vertices;
var faces:Array = mesh.geometry.faces;
// vertex チャンクを検索
var vline:int = getChunkLine(lines, "vertex", l);
if (vline == -1) {
return -1;
}
// プロパティを読み込む
var properties:Dictionary = new Dictionary();
for (; l < vline; ++l) {
line = lines[l];
var props:Array = RegExp(/^\s*([\w]+)\s+(.*)$/).exec(line);
properties[props[1]] = props[2];
}
line = lines[l];
l = vline + 1;
// 頂点数を取得
var numVertices:int = parseInt(line.substring(line.indexOf("vertex") + 7));
var vertexEndLine:int = l + numVertices;
var firstVertexIndex:int = vertices.length;
// vertex チャンクを読み込む
for (; l < vertexEndLine; ++l) {
line = lines[l];
var coords:Array = line.match(/(-?\d+\.\d+)/g);
var x:Number = parseFloat(coords[0]) * _scale;
var y:Number = parseFloat(coords[1]) * _scale;
var z:Number = -parseFloat(coords[2]) * _scale;
vertices.push(new Vertex3D(x, y, z));
}
// face チャンクを検索
l = getChunkLine(lines, "face", l);
if (l == -1) {
return -1;
}
line = lines[l++];
// 面数を取得
var numFaces:int = parseInt(line.substring(line.indexOf("face") + 5));
var faceEndLine:int = l + numFaces;
// face チャンクを読み込む
for (; l < faceEndLine; ++l) {
if (properties["visible"] == "15") {
parseFace(faces, lines[l], vertices, firstVertexIndex, properties);
}
}
// Resolve parent-child relationship.
var depth:int;
try {
depth = parseInt(properties["depth"]);
} catch (e:Error) {
depth = 0;
}
var parentMesh:DisplayObjectContainer3D = _prevMesh;
if (depth <= 0) {
parentMesh = this;
depth = 0;
} else {
while (depth <= _prevDepth) {
parentMesh = DisplayObject3D(parentMesh).parent;
--_prevDepth;
}
}
parentMesh.addChild(mesh);
_prevMesh = mesh;
_prevDepth = depth;
return l;
}
private function parseFace(faces:Array, line:String, vertices:Array, vertexOffset:int,
properties:Dictionary):void {
var vstr:String = getParam(line, "V");
var mstr:String = getParam(line, "M");
var uvstr:String = getParam(line, "UV");
var v:Array = (vstr != null) ? vstr.match(/\d+/g) : [];
var uv:Array = (uvstr != null) ? uvstr.match(/-?\d+\.\d+/g) : [];
var a:Vertex3D;
var b:Vertex3D;
var c:Vertex3D;
var d:Vertex3D;
var material:MaterialObject3D;
var uvA:NumberUV;
var uvB:NumberUV;
var uvC:NumberUV;
var uvD:NumberUV;
var face:Triangle3D;
if (v.length == 3) {
c = vertices[parseInt(v[0]) + vertexOffset];
b = vertices[parseInt(v[1]) + vertexOffset];
a = vertices[parseInt(v[2]) + vertexOffset];
if (mstr != null) {
material = materials.getMaterialByName(_materialNames[parseInt(mstr)]);
}
if (uv.length != 0) {
uvC = new NumberUV(parseFloat(uv[0]), 1 - parseFloat(uv[1]));
uvB = new NumberUV(parseFloat(uv[2]), 1 - parseFloat(uv[3]));
uvA = new NumberUV(parseFloat(uv[4]), 1 - parseFloat(uv[5]));
face = new Triangle3D(this, [a, b, c], material, [uvA, uvB, uvC]);
} else {
face = new Triangle3D(this, [a, b, c], material,
[new NumberUV(0, 0), new NumberUV(1, 0), new NumberUV(0, 1)]);
}
faces.push(face);
if (properties["mirror"] == "1") {
var mirrorAxis:int = parseInt(properties["mirror_axis"]);
a = mirrorVertex(a, mirrorAxis);
b = mirrorVertex(b, mirrorAxis);
c = mirrorVertex(c, mirrorAxis);
vertices.push(a);
vertices.push(b);
vertices.push(c);
face = new Triangle3D(this, [c, b, a], material, face.uv.reverse());
faces.push(face);
}
} else if (v.length == 4) {
d = vertices[parseInt(v[0]) + vertexOffset];
c = vertices[parseInt(v[1]) + vertexOffset];
b = vertices[parseInt(v[2]) + vertexOffset];
a = vertices[parseInt(v[3]) + vertexOffset];
if (mstr != null) {
material = materials.getMaterialByName(_materialNames[parseInt(mstr)]);
}
if (uv.length != 0) {
uvD = new NumberUV(parseFloat(uv[0]), 1 - parseFloat(uv[1]));
uvC = new NumberUV(parseFloat(uv[2]), 1 - parseFloat(uv[3]));
uvB = new NumberUV(parseFloat(uv[4]), 1 - parseFloat(uv[5]));
uvA = new NumberUV(parseFloat(uv[6]), 1 - parseFloat(uv[7]));
} else {
uvD = new NumberUV(0, 0);
uvC = new NumberUV(1, 0);
uvB = new NumberUV(0, 1);
uvA = new NumberUV(1, 1);
}
face = new Triangle3D(this, [a, b, c], material, [uvA, uvB, uvC]);
faces.push(face);
face = new Triangle3D(this, [c, d, a], material, [uvC, uvD, uvA]);
faces.push(face);
if (properties["mirror"] == "1") {
mirrorAxis = parseInt(properties["mirror_axis"]);
a = mirrorVertex(a, mirrorAxis);
b = mirrorVertex(b, mirrorAxis);
c = mirrorVertex(c, mirrorAxis);
d = mirrorVertex(d, mirrorAxis);
vertices.push(a);
vertices.push(b);
vertices.push(c);
vertices.push(d);
face = new Triangle3D(this, [c, b, a], material, [uvC, uvB, uvA]);
faces.push(face);
face = new Triangle3D(this, [a, d, c], material, [uvA, uvD, uvC]);
faces.push(face);
}
}
}
/**
* 頂点を軸に沿って反転させたものを返します。
*/
private static function mirrorVertex(v:Vertex3D, axis:int):Vertex3D {
return new Vertex3D(
((axis & 1) != 0) ? -v.x : v.x,
((axis & 2) != 0) ? -v.y : v.y,
((axis & 4) != 0) ? -v.z : v.z);
}
/**
* Object チャンクの開始行を返します。
*/
private static function getChunkLine(lines:Array, chunkName:String, startLine:int = 0):int {
for (var i:uint = startLine; i < lines.length; ++i) {
if (lines[i].indexOf(chunkName) != -1) {
return int(i);
}
}
return -1;
}
/**
* line 内で paramName(...) という形式で指定されているパラメータを返します。
*/
private static function getParam(line:String, paramName:String):String {
var prefix:String = paramName + "(";
var prefixLen:int = prefix.length;
var begin:int = line.indexOf(prefix, 0);
if (begin == -1) {
return null;
}
var end:int = line.indexOf(")", begin + prefixLen);
if (end == -1){
return null;
}
return line.substring(begin + prefixLen, end);
}
}
//}
/**
* TGADecoder.as
*
* @see http://snippets.libspark.org/
* @see http://snippets.libspark.org/trac/wiki/rch850/Metasequoia
*
* Copyright (c) 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.decoders {
import flash.display.BitmapData;
import flash.utils.ByteArray;
import flash.utils.Endian;
class TGADecoder {
//___________________________________________________________ const
// constant value for _imageType
private const TYPE_NONE:uint = 0x00;
private const TYPE_INDEX_COLOR:uint = 0x01;
private const TYPE_FULL_COLOR:uint = 0x02;
private const TYPE_RLE_BIT:uint = 0x08;
private const DIR_RIGHT_UP:int = 0;
private const DIR_LEFT_UP:int = 1;
private const DIR_RIGHT_DOWN:int = 2;
private const DIR_LEFT_DOWN:int = 3;
//___________________________________________________________ vars
private var _bitmap:BitmapData;
public function get bitmap():BitmapData {
return _bitmap;
}
private var _idLength:int; // byte
private var _colorMapType:int; // byte
private var _imageType:int; // byte
private var _colorMapIndex:int; // short
private var _colorMapLength:int; // short
private var _colorMapSize:int; // byte
private var _originX:int; // short
private var _originY:int; // short
private var _width:int; // short
public function get width():int {
return _width;
}
private var _height:int; // short
public function get height():int {
return _height;
}
private var _bitDepth:int; // byte
private var _descriptor:int; // byte
public function get pixelDirection():int {
// descriptor:
// 4th bit: 0 = left to right, 1 = right to left
// 5th bit: 0 = bottom up, 1 = top down
return (_descriptor >> 4) & 3;
}
/**
* Construct TGA file from ByteArray.
*/
public function TGADecoder(bytes:ByteArray) {
bytes.position = 0;
bytes.endian = Endian.LITTLE_ENDIAN;
_idLength = bytes.readByte();
_colorMapType = bytes.readByte();
_imageType = bytes.readByte();
_colorMapIndex = bytes.readShort();
_colorMapLength = bytes.readShort();
_colorMapSize = bytes.readByte()
_originX = bytes.readShort();
_originY = bytes.readShort();
_width = bytes.readShort();
_height = bytes.readShort();
_bitDepth = bytes.readByte();
_descriptor = bytes.readByte();
_bitmap = new BitmapData(_width, _height);
// ignore unsupported formats.
if ((_imageType & TYPE_FULL_COLOR) == 0
|| (_imageType & TYPE_RLE_BIT) != 0) {
throw new Error("Unsupported tga format.");
}
_bitmap.lock();
try {
if (_bitDepth == 32) {
loadBitmap32(bytes);
} else if (_bitDepth == 24) {
loadBitmap24(bytes);
}
} finally {
_bitmap.unlock();
}
}
/**
* Load 32 bpp bitmap.
*/
private function loadBitmap32(bytes:ByteArray):void {
var x:int, y:int;
switch (pixelDirection) {
case DIR_RIGHT_UP:
for (y = _bitmap.height - 1; y >= 0; --y) {
for (x = 0; x < _bitmap.width; ++x) {
_bitmap.setPixel32(x, y, bytes.readUnsignedInt());
}
}
break;
case DIR_LEFT_UP:
for (y = _bitmap.height - 1; y >= 0; --y) {
for (x = _bitmap.width - 1; x >= 0; --x) {
_bitmap.setPixel32(x, y, bytes.readUnsignedInt());
}
}
break;
case DIR_RIGHT_DOWN:
for (y = 0; y < _bitmap.height; ++y) {
for (x = 0; x < _bitmap.width; ++x) {
_bitmap.setPixel32(x, y, bytes.readUnsignedInt());
}
}
break;
case DIR_LEFT_DOWN:
for (y = 0; y < _bitmap.height; ++y) {
for (x = _bitmap.width - 1; x >= 0; --x) {
_bitmap.setPixel32(x, y, bytes.readUnsignedInt());
}
}
break;
}
}
/**
* Load 24 bpp bitmap.
*/
private function loadBitmap24(bytes:ByteArray):void {
var x:int, y:int;
var r:uint, g:uint, b:uint;
switch (pixelDirection) {
case DIR_RIGHT_UP:
for (y = _bitmap.height - 1; y >= 0; --y) {
for (x = 0; x < _bitmap.width; ++x) {
b = bytes.readUnsignedByte();
g = bytes.readUnsignedByte();
r = bytes.readUnsignedByte();
_bitmap.setPixel32(x, y, 0xFF000000 | (r << 16) | (g << 8) | b);
}
}
break;
case DIR_LEFT_UP:
for (y = _bitmap.height - 1; y >= 0; --y) {
for (x = _bitmap.width - 1; x >= 0; --x) {
b = bytes.readUnsignedByte();
g = bytes.readUnsignedByte();
r = bytes.readUnsignedByte();
_bitmap.setPixel32(x, y, 0xFF000000 | (r << 16) | (g << 8) | b);
}
}
break;
case DIR_RIGHT_DOWN:
for (y = 0; y < _bitmap.height; ++y) {
for (x = 0; x < _bitmap.width; ++x) {
b = bytes.readUnsignedByte();
g = bytes.readUnsignedByte();
r = bytes.readUnsignedByte();
_bitmap.setPixel32(x, y, 0xFF000000 | (r << 16) | (g << 8) | b);
}
}
break;
case DIR_LEFT_DOWN:
for (y = 0; y < _bitmap.height; ++y) {
for (x = _bitmap.width - 1; x >= 0; --x) {
b = bytes.readUnsignedByte();
g = bytes.readUnsignedByte();
r = bytes.readUnsignedByte();
_bitmap.setPixel32(x, y, 0xFF000000 | (r << 16) | (g << 8) | b);
}
}
break;
}
}
}
//}
/**
* com.voidelement.images.BMPDecoder Class for ActionScript 3.0
*
* @author Copyright (c) 2007 munegon
* @version 1.0
*
* @link http://www.voidelement.com/
* @link http://void.heteml.jp/blog/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
//package com.voidelement.images {
import flash.display.BitmapData;
import flash.errors.IOError;
import flash.utils.ByteArray;
import flash.utils.Endian;
class BMPDecoder {
//___________________________________________________________ const
private const BITMAP_HEADER_TYPE:String = "BM";
private const BITMAP_FILE_HEADER_SIZE:int = 14;
private const BITMAP_CORE_HEADER_SIZE:int = 12;
private const BITMAP_INFO_HEADER_SIZE:int = 40;
private const COMP_RGB :int = 0;
private const COMP_RLE8 :int = 1;
private const COMP_RLE4 :int = 2;
private const COMP_BITFIELDS:int = 3;
private const BIT1 :int = 1;
private const BIT4 :int = 4;
private const BIT8 :int = 8;
private const BIT16:int = 16;
private const BIT24:int = 24;
private const BIT32:int = 32;
//___________________________________________________________ vars
private var bytes:ByteArray;
private var palette:Array;
private var bd:BitmapData;
private var nFileSize:uint;
private var nReserved1:uint;
private var nReserved2:uint;
private var nOffbits:uint;
private var nInfoSize:uint;
private var nWidth:int;
private var nHeight:int;
private var nPlains:uint;
private var nBitsPerPixel:uint;
private var nCompression:uint;
private var nSizeImage:uint;
private var nXPixPerMeter:int;
private var nYPixPerMeter:int;
private var nColorUsed:uint;
private var nColorImportant:uint;
private var nRMask:uint;
private var nGMask:uint;
private var nBMask:uint;
private var nRPos:uint;
private var nGPos:uint;
private var nBPos:uint;
private var nRMax:uint;
private var nGMax:uint;
private var nBMax:uint;
/**
* コンストラクタ
*/
public function BMPDecoder() {
nRPos = 0;
nGPos = 0;
nBPos = 0;
}
/**
* デコード
*
* @param デコードしたいBMPファイルのバイナリデータ
*/
public function decode( data:ByteArray ):BitmapData {
bytes = data;
bytes.endian = Endian.LITTLE_ENDIAN;
bytes.position = 0;
readFileHeader();
nInfoSize = bytes.readUnsignedInt();
switch ( nInfoSize ) {
case BITMAP_CORE_HEADER_SIZE:
readCoreHeader();
break;
case BITMAP_INFO_HEADER_SIZE:
readInfoHeader();
break;
default:
readExtendedInfoHeader();
break;
}
bd = new BitmapData( nWidth, nHeight );
switch ( nBitsPerPixel ){
case BIT1:
readColorPalette();
decode1BitBMP();
break;
case BIT4:
readColorPalette();
if ( nCompression == COMP_RLE4 ){
decode4bitRLE();
} else {
decode4BitBMP();
}
break;
case BIT8:
readColorPalette();
if ( nCompression == COMP_RLE8 ){
decode8BitRLE();
} else {
decode8BitBMP();
}
break;
case BIT16:
readBitFields();
checkColorMask();
decode16BitBMP();
break;
case BIT24:
decode24BitBMP();
break;
case BIT32:
readBitFields();
checkColorMask();
decode32BitBMP();
break;
default:
throw new VerifyError("invalid bits per pixel : " + nBitsPerPixel );
}
return bd;
}
/**
* BITMAP FILE HEADER 読み込み
*/
private function readFileHeader():void {
var fileHeader:ByteArray = new ByteArray();
fileHeader.endian = Endian.LITTLE_ENDIAN;
try {
bytes.readBytes( fileHeader, 0, BITMAP_FILE_HEADER_SIZE );
if ( fileHeader.readUTFBytes( 2 ) != BITMAP_HEADER_TYPE ){
throw new VerifyError("invalid bitmap header type");
}
nFileSize = fileHeader.readUnsignedInt();
nReserved1 = fileHeader.readUnsignedShort();
nReserved2 = fileHeader.readUnsignedShort();
nOffbits = fileHeader.readUnsignedInt();
} catch ( e:IOError ) {
throw new VerifyError("invalid file header");
}
}
/**
* BITMAP CORE HEADER 読み込み
*/
private function readCoreHeader():void {
var coreHeader:ByteArray = new ByteArray();
coreHeader.endian = Endian.LITTLE_ENDIAN;
try {
bytes.readBytes( coreHeader, 0, BITMAP_CORE_HEADER_SIZE - 4 );
nWidth = coreHeader.readShort();
nHeight = coreHeader.readShort();
nPlains = coreHeader.readUnsignedShort();
nBitsPerPixel = coreHeader.readUnsignedShort();
} catch ( e:IOError ) {
throw new VerifyError("invalid core header");
}
}
/**
* BITMAP INFO HEADER 読み込み
*/
private function readInfoHeader():void {
var infoHeader:ByteArray = new ByteArray();
infoHeader.endian = Endian.LITTLE_ENDIAN;
try {
bytes.readBytes( infoHeader, 0, BITMAP_INFO_HEADER_SIZE - 4 );
nWidth = infoHeader.readInt();
nHeight = infoHeader.readInt();
nPlains = infoHeader.readUnsignedShort();
nBitsPerPixel = infoHeader.readUnsignedShort();
nCompression = infoHeader.readUnsignedInt();
nSizeImage = infoHeader.readUnsignedInt();
nXPixPerMeter = infoHeader.readInt();
nYPixPerMeter = infoHeader.readInt();
nColorUsed = infoHeader.readUnsignedInt();
nColorImportant = infoHeader.readUnsignedInt();
} catch ( e:IOError ) {
throw new VerifyError("invalid info header");
}
}
/**
* 拡張 BITMAP INFO HEADER 読み込み
*/
private function readExtendedInfoHeader():void {
var infoHeader:ByteArray = new ByteArray();
infoHeader.endian = Endian.LITTLE_ENDIAN;
try {
bytes.readBytes( infoHeader, 0, nInfoSize - 4 );
nWidth = infoHeader.readInt();
nHeight = infoHeader.readInt();
nPlains = infoHeader.readUnsignedShort();
nBitsPerPixel = infoHeader.readUnsignedShort();
nCompression = infoHeader.readUnsignedInt();
nSizeImage = infoHeader.readUnsignedInt();
nXPixPerMeter = infoHeader.readInt();
nYPixPerMeter = infoHeader.readInt();
nColorUsed = infoHeader.readUnsignedInt();
nColorImportant = infoHeader.readUnsignedInt();
if ( infoHeader.bytesAvailable >= 4 ) nRMask = infoHeader.readUnsignedInt();
if ( infoHeader.bytesAvailable >= 4 ) nGMask = infoHeader.readUnsignedInt();
if ( infoHeader.bytesAvailable >= 4 ) nBMask = infoHeader.readUnsignedInt();
} catch ( e:IOError ) {
throw new VerifyError("invalid info header");
}
}
/**
* ビットフィールド読み込み
*/
private function readBitFields():void {
if ( nCompression == COMP_RGB ){
if ( nBitsPerPixel == BIT16 ){
// RGB555
nRMask = 0x00007c00;
nGMask = 0x000003e0;
nBMask = 0x0000001f;
} else {
//RGB888;
nRMask = 0x00ff0000;
nGMask = 0x0000ff00;
nBMask = 0x000000ff;
}
} else if ( ( nCompression == COMP_BITFIELDS ) && ( nInfoSize < 52 ) ){
try {
nRMask = bytes.readUnsignedInt();
nGMask = bytes.readUnsignedInt();
nBMask = bytes.readUnsignedInt();
} catch ( e:IOError ) {
throw new VerifyError("invalid bit fields");
}
}
}
/**
* カラーパレット読み込み
*/
private function readColorPalette():void {
var i:int;
var len:int = ( nColorUsed > 0 ) ? nColorUsed : Math.pow( 2, nBitsPerPixel );
palette = new Array( len );
for ( i = 0; i < len; ++i ){
palette[ i ] = bytes.readUnsignedInt();
}
}
/**
* 1bitのBMPデコード
*/
private function decode1BitBMP():void {
var x:int;
var y:int;
var i:int;
var col:int;
var buf:ByteArray = new ByteArray();
var line:int = nWidth / 8;
if ( line % 4 > 0 ){
line = ( ( line / 4 | 0 ) + 1 ) * 4;
}
try {
for ( y = nHeight - 1; y >= 0; --y ){
buf.length = 0;
bytes.readBytes( buf, 0, line );
for ( x = 0; x < nWidth; x += 8 ){
col = buf.readUnsignedByte();
for ( i = 0; i < 8; ++i ){
bd.setPixel( x + i, y, palette[ col >> ( 7 - i ) & 0x01 ] );
}
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* 4bitのRLE圧縮BMPデコード
*/
private function decode4bitRLE():void {
var x:int;
var y:int;
var i:int;
var n:int;
var col:int;
var data:uint;
var buf:ByteArray = new ByteArray();
try {
for ( y = nHeight - 1; y >= 0; --y ){
buf.length = 0;
while ( bytes.bytesAvailable > 0 ){
n = bytes.readUnsignedByte();
if ( n > 0 ){
// エンコードデータ
data = bytes.readUnsignedByte();
for ( i = 0; i < n/2; ++i ){
buf.writeByte( data );
}
} else {
n = bytes.readUnsignedByte();
if ( n > 0 ){
// 絶対モードデータ
bytes.readBytes( buf, buf.length, n/2 );
buf.position += n/2;
if ( n/2 + 1 >> 1 << 1 != n/2 ){
bytes.readUnsignedByte();
}
} else {
// EOL
break;
}
}
}
buf.position = 0;
for ( x = 0; x < nWidth; x += 2 ){
col = buf.readUnsignedByte();
bd.setPixel( x, y, palette[ col >> 4 ] );
bd.setPixel( x + 1, y, palette[ col & 0x0f ] );
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* 4bitの非圧縮BMPデコード
*/
private function decode4BitBMP():void {
var x:int;
var y:int;
var i:int;
var col:int;
var buf:ByteArray = new ByteArray();
var line:int = nWidth / 2;
if ( line % 4 > 0 ){
line = ( ( line / 4 | 0 ) + 1 ) * 4;
}
try {
for ( y = nHeight - 1; y >= 0; --y ){
buf.length = 0;
bytes.readBytes( buf, 0, line );
for ( x = 0; x < nWidth; x += 2 ){
col = buf.readUnsignedByte();
bd.setPixel( x, y, palette[ col >> 4 ] );
bd.setPixel( x + 1, y, palette[ col & 0x0f ] );
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* 8bitのRLE圧縮BMPデコード
*/
private function decode8BitRLE():void {
var x:int;
var y:int;
var i:int;
var n:int;
var col:int;
var data:uint;
var buf:ByteArray = new ByteArray();
try {
for ( y = nHeight - 1; y >= 0; --y ){
buf.length = 0;
while ( bytes.bytesAvailable > 0 ){
n = bytes.readUnsignedByte();
if ( n > 0 ){
// エンコードデータ
data = bytes.readUnsignedByte();
for ( i = 0; i < n; ++i ){
buf.writeByte( data );
}
} else {
n = bytes.readUnsignedByte();
if ( n > 0 ){
// 絶対モードデータ
bytes.readBytes( buf, buf.length, n );
buf.position += n;
if ( n + 1 >> 1 << 1 != n ){
bytes.readUnsignedByte();
}
} else {
// EOL
break;
}
}
}
buf.position = 0;
for ( x = 0; x < nWidth; ++x ){
bd.setPixel( x, y, palette[ buf.readUnsignedByte() ] );
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* 8bitの非圧縮BMPデコード
*/
private function decode8BitBMP():void {
var x:int;
var y:int;
var i:int;
var col:int;
var buf:ByteArray = new ByteArray();
var line:int = nWidth;
if ( line % 4 > 0 ){
line = ( ( line / 4 | 0 ) + 1 ) * 4;
}
try {
for ( y = nHeight - 1; y >= 0; --y ){
buf.length = 0;
bytes.readBytes( buf, 0, line );
for ( x = 0; x < nWidth; ++x ){
bd.setPixel( x, y, palette[ buf.readUnsignedByte() ] );
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* 16bitのBMPデコード
*/
private function decode16BitBMP():void {
var x:int;
var y:int;
var col:int;
try {
for ( y = nHeight - 1; y >= 0; --y ){
for ( x = 0; x < nWidth; ++x ){
col = bytes.readUnsignedShort();
bd.setPixel( x, y, ( ( ( col & nRMask ) >> nRPos )*0xff/nRMax << 16 ) + ( ( ( col & nGMask ) >> nGPos )*0xff/nGMax << 8 ) + ( ( ( col & nBMask ) >> nBPos )*0xff/nBMax << 0 ) );
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* 24bitのBMPデコード
*/
private function decode24BitBMP():void {
var x:int;
var y:int;
var col:int;
var buf:ByteArray = new ByteArray();
var line:int = nWidth * 3;
if ( line % 4 > 0 ){
line = ( ( line / 4 | 0 ) + 1 ) * 4;
}
try {
for ( y = nHeight - 1; y >= 0; --y ){
buf.length = 0;
bytes.readBytes( buf, 0, line );
for ( x = 0; x < nWidth; ++x ){
bd.setPixel( x, y, buf.readUnsignedByte() + ( buf.readUnsignedByte() << 8 ) + ( buf.readUnsignedByte() << 16 ) );
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* 32bitのBMPデコード
*/
private function decode32BitBMP():void {
var x:int;
var y:int;
var col:int;
try {
for ( y = nHeight - 1; y >= 0; --y ){
for ( x = 0; x < nWidth; ++x ){
col = bytes.readUnsignedInt();
bd.setPixel( x, y, ( ( ( col & nRMask ) >> nRPos )*0xff/nRMax << 16 ) + ( ( ( col & nGMask ) >> nGPos )*0xff/nGMax << 8 ) + ( ( ( col & nBMask ) >> nBPos )*0xff/nBMax << 0 ) );
}
}
} catch ( e:IOError ) {
throw new VerifyError("invalid image data");
}
}
/**
* カラーマスクチェック
*/
private function checkColorMask():void {
if ( ( nRMask & nGMask ) | ( nGMask & nBMask ) | ( nBMask & nRMask ) ){
throw new VerifyError("invalid bit fields");
}
while ( ( ( nRMask >> nRPos ) & 0x00000001 ) == 0 ){
nRPos++;
}
while ( ( ( nGMask >> nGPos ) & 0x00000001 ) == 0 ){
nGPos++;
}
while ( ( ( nBMask >> nBPos ) & 0x00000001 ) == 0 ){
nBPos++;
}
nRMax = nRMask >> nRPos;
nGMax = nGMask >> nGPos;
nBMax = nBMask >> nBPos;
}
/**
* 情報出力
*/
public function traceInfo():void {
trace("---- FILE HEADER ----");
trace("nFileSize: " + nFileSize );
trace("nReserved1: " + nReserved1 );
trace("nReserved2: " + nReserved2 );
trace("nOffbits: " + nOffbits );
trace("---- INFO HEADER ----");
trace("nWidth: " + nWidth );
trace("nHeight: " + nHeight );
trace("nPlains: " + nPlains );
trace("nBitsPerPixel: " + nBitsPerPixel );
if ( nInfoSize >= 40 ){
trace("nCompression: " + nCompression );
trace("nSizeImage: " + nSizeImage );
trace("nXPixPerMeter: " + nXPixPerMeter );
trace("nYPixPerMeter: " + nYPixPerMeter );
trace("nColorUsed: " + nColorUsed );
trace("nColorUsed: " + nColorImportant );
}
if ( nInfoSize >= 52 ){
trace("nRMask: " + nRMask.toString( 2 ) );
trace("nGMask: " + nGMask.toString( 2 ) );
trace("nBMask: " + nBMask.toString( 2 ) );
}
}
}
//}