root/as3/Metasequoia/src/org/libspark/away3d/Metasequoia.as

リビジョン 1906, 11.2 kB (コミッタ: nanmo, コミット時期: 3 年 前)

Fix multiple Metasequoia file's texture loading

Line 
1 /**
2  * Metasequoia.as
3  *
4  * @see http://snippets.libspark.org/
5  * @see http://www.libspark.org/wiki/nanmo/Metasequoia
6  *
7  * Copyright (c) 2008 nanmo
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  */
27
28 /**
29  * History
30  * Make Metasequoia.as(original) by rch850
31  *  in http://snippets.libspark.org/trac/wiki/rch850/Metasequoia
32  * Modify Metasequoia.as for Away3D by katopz@sleepydesign.com
33  *  in http://sleepydesign.blogspot.com/2008/05/away3d-metasequoia-mqo.html
34  * Modify Metasequoia.as for Away3D v2.2 by nanmo
35  *  in http://www.libspark.org/wiki/nanmo/Metasequoia
36 */
37 package org.libspark.away3d
38 {
39         import away3d.containers.ObjectContainer3D;
40     import away3d.core.*;
41     import away3d.core.math.*;
42     import away3d.core.base.*
43     import away3d.core.base.*;
44         import away3d.loaders.utils.MaterialLibrary;
45     import away3d.materials.*;
46     import away3d.core.utils.*;
47     import away3d.core.stats.*;
48         import away3d.loaders.*;
49     import flash.utils.*;
50        
51         public class Metasequoia extends AbstractParser {
52                 use namespace arcane;
53                 /** @private */
54         arcane var ini:Init;
55                
56                 public var charset:String = "shift_jis";
57
58                 private var mesh:Mesh;
59         private var scaling:Number;
60                
61                 public var materialLibrary:MaterialLibrary;
62                 private var _materialNames:Array;
63                 private var _filename:String;
64                
65                 function Metasequoia (data:ByteArray, init:Object = null)
66                 {
67                         container = new ObjectContainer3D(ini);
68                         container.name = "Metasequoia";
69                        
70             init = Init.parse(init);
71                         _filename = init.getString("filename", "");
72             scaling = init.getNumber("scaling", 1)*100;
73                        
74             mesh = new Mesh(init);
75                        
76             parseMetasequoia(data);
77                        
78                         container = mesh;
79                 }
80         public static function parse(data:*, init:Object = null, loader:Object3DLoader = null):Mesh
81         {
82             return new Metasequoia(Cast.bytearray(data), init).mesh;
83         }
84         public static function load(url:String, init:Object = null):Object3DLoader
85         {
86                         init.filename = url;
87             return Object3DLoader.loadGeometry(url, Metasequoia, true, init);
88         }
89
90         private function parseMetasequoia(data:ByteArray):void
91         {
92                        
93                         var byteArray:ByteArray = ByteArray(data);
94                         var plainText:String = byteArray.readMultiByte(byteArray.length, charset);
95                        
96                         var lines:Array = plainText.split("\r\n");
97                         var l:int = 0;
98                        
99                         l = parseMaterialChunk(lines, 0);
100                        
101                         while (l != -1) {
102                                 l = parseObjectChunk(lines, l);
103                         }
104                        
105                         mesh.type = ".Mqo";
106                 }
107                
108                 private function getMaterialChunkLine(lines:Array, startLine:int = 0):int {
109                         for (var i:uint = startLine; i < lines.length; ++i) {
110                                 if (lines[i].indexOf("Material") == 0) {
111                                         return int(i);
112                                 }
113                         }
114                         return -1;
115                 }
116                
117                 private function parseMaterialChunk(lines:Array, startLine:int):int {
118                         materialLibrary = new MaterialLibrary();
119                         var l:int = getMaterialChunkLine(lines, startLine);
120                         if (l == -1) {
121                                 return -1;
122                         }
123                        
124                         var line:String = lines[l];
125                        
126                         var num:Number = parseInt(line.substr(9));
127                         if (isNaN(num)) {
128                                 return -1;
129                         }
130                         ++l;
131                         _materialNames = new Array();
132                        
133                         var endLine:int = l + int(num);
134                        
135                         //Get Mqo file directory
136                         var path:String = _filename.slice(0, _filename.lastIndexOf("/") + 1);
137                        
138                         for (; l < endLine; ++l) {
139                                 var _material:ITriangleMaterial;
140                                 line = lines[l];
141                                
142                                 var nameBeginIndex:int = line.indexOf("\"");
143                                 var nameEndIndex:int = line.indexOf("\"", nameBeginIndex + 1);
144                                 var name:String = line.substring(nameBeginIndex + 1, nameEndIndex);
145                                 _materialNames.push(name);
146                                
147                                 var tex:String = getParam(line, "tex");
148                                
149                                 if (tex) {
150                                         tex = tex.substr(1, tex.length - 2);
151                                         _material = new BitmapFileMaterial(path + tex,{repeat:true});
152                                 } else {
153                                         var colorstr:String = getParam(line, "col");
154                                         if (colorstr != null) {
155                                                 var color:Array = colorstr.match(/\d+\.\d+/g);
156                                                 var r:int = parseFloat(color[0]) * 255;
157                                                 var g:int = parseFloat(color[1]) * 255;
158                                                 var b:int = parseFloat(color[2]) * 255;
159                                                 var a:Number = parseFloat(color[3]);
160                                                 _material = new ColorMaterial((r << 16) | (g << 8) | b,{alpha:a});
161                                         } else {
162                                                 //_material = ITriangleMaterial.DEFAULT;
163                                         }
164                                 }
165                                
166                                 materialLibrary[name] = _material;
167                                
168                         }
169                        
170                         return endLine;
171                 }
172                
173                 private function getObjectChunkLine(lines:Array, startLine:int = 0):int {
174                         for (var i:uint = startLine; i < lines.length; ++i) {
175                                 if (lines[i].indexOf("Object") == 0) {
176                                         return int(i);
177                                 }
178                         }
179                         return -1;
180                 }
181                
182                 private function parseObjectChunk(lines:Array, startLine:int):int {
183                        
184             var vertices:Array = [];
185             var faces:Array = [];
186                        
187                         var l:int = getObjectChunkLine(lines, startLine);
188                         if (l == -1) {
189                                 return -1;
190                         }
191                        
192                         var line:String = lines[l];
193                        
194                         var objectName:String = line.substring(8, line.indexOf("\"", 8));
195                         ++l;
196                        
197                         var vline:int = getChunkLine(lines, "vertex", l);
198                         if (vline == -1) {
199                                 return -1;
200                         }
201                        
202                         var properties:Dictionary = new Dictionary();
203                         for (; l < vline; ++l) {
204                                 line = lines[l];
205                                 var props:Array = RegExp(/^\s*([\w]+)\s+(.*)$/).exec(line);
206                                 properties[props[1]] = props[2];
207                         }
208                        
209                         line = lines[l];
210                         l = vline + 1;
211                        
212                         var numVertices:int = parseInt(line.substring(line.indexOf("vertex") + 7));
213                         var vertexEndLine:int = l + numVertices;
214                         var firstVertexIndex:int = vertices.length;
215                        
216                         for (; l < vertexEndLine; ++l) {
217                                 line = lines[l];
218                                 var coords:Array = line.match(/(-?\d+\.\d+)/g);
219                                 var x:Number = parseFloat(coords[0]) * scaling;
220                                 var y:Number = parseFloat(coords[1]) * scaling;
221                                 var z:Number = -parseFloat(coords[2]) * scaling;
222                 vertices.push(new Vertex(x,y,z));
223                         }
224                        
225                         l = getChunkLine(lines,  "face", l);
226                         if (l == -1) {
227                                 return -1;
228                         }
229                         line = lines[l++];
230                        
231                         var numFaces:int = parseInt(line.substring(line.indexOf("face") + 5));
232                         var faceEndLine:int = l + numFaces;
233                        
234                         for (; l < faceEndLine; ++l) {
235                                 if (properties["visible"] == "15") {
236                                         parseFace(faces, lines[l], vertices, firstVertexIndex, properties);
237                                 }
238                         }
239                        
240                         return faceEndLine;
241                 }
242                
243                 private function parseFace(faces:Array, line:String, vertices:Array, vertexOffset:int, properties:Dictionary):void {
244                         var vstr:String = getParam(line, "V");
245                         var mstr:String = getParam(line, "M");
246                         var uvstr:String = getParam(line, "UV");
247                        
248                         var v:Array = (vstr != null) ? vstr.match(/\d+/g) : [];
249                         var uv:Array = (uvstr != null) ? uvstr.match(/-?\d+\.\d+/g) : [];
250                         var a:Vertex;
251                         var b:Vertex;
252                         var c:Vertex;
253                         var d:Vertex;
254                         var _material:ITriangleMaterial;
255                         var uvA:UV;
256                         var uvB:UV;
257                         var uvC:UV;
258                         var uvD:UV;
259                         var face:Face;
260                        
261                         if (v.length == 3) {
262                                 c = vertices[parseInt(v[0]) + vertexOffset];
263                                 b = vertices[parseInt(v[1]) + vertexOffset];
264                                 a = vertices[parseInt(v[2]) + vertexOffset];
265                                
266                                 if (mstr != null) {
267                                         _material = materialLibrary[_materialNames[parseInt(mstr)]];
268                                 }
269                                
270                                 if (uv.length != 0) {
271                                         uvC = new UV(parseFloat(uv[0]), 1 - parseFloat(uv[1]));
272                                         uvB = new UV(parseFloat(uv[2]), 1 - parseFloat(uv[3]));
273                                         uvA = new UV(parseFloat(uv[4]), 1 - parseFloat(uv[5]));
274                                         face = new Face(a, b, c, _material, uvA, uvB, uvC);
275                                 } else {
276                                         face = new Face(a, b, c, _material, new UV(0, 0), new UV(1, 0), new UV(0, 1));
277                                 }
278                                 mesh.addFace(face);
279                                
280                                 if (properties["mirror"] == "1") {
281                                         var mirrorAxis:int = parseInt(properties["mirror_axis"]);
282                                         a = mirrorVertex(a, mirrorAxis);
283                                         b = mirrorVertex(b, mirrorAxis);
284                                         c = mirrorVertex(c, mirrorAxis);
285                                         vertices.push(a);
286                                         vertices.push(b);
287                                         vertices.push(c);
288                                         face = new Face( c, b, a, _material, uvC, uvB, uvA);
289                                         mesh.addFace(face);
290                                 }
291                         } else if (v.length == 4) {
292                                 d = vertices[parseInt(v[0]) + vertexOffset];
293                                 c = vertices[parseInt(v[1]) + vertexOffset];
294                                 b = vertices[parseInt(v[2]) + vertexOffset];
295                                 a = vertices[parseInt(v[3]) + vertexOffset];
296                                
297                                 if (mstr != null) {
298                                         _material = materialLibrary[_materialNames[parseInt(mstr)]];
299                                 }
300                                
301                                 if (uv.length != 0) {
302                                         uvD = new UV(parseFloat(uv[0]), 1 - parseFloat(uv[1]));
303                                         uvC = new UV(parseFloat(uv[2]), 1 - parseFloat(uv[3]));
304                                         uvB = new UV(parseFloat(uv[4]), 1 - parseFloat(uv[5]));
305                                         uvA = new UV(parseFloat(uv[6]), 1 - parseFloat(uv[7]));
306                                 } else {
307                                         uvD = new UV(0, 0);
308                                         uvC = new UV(1, 0);
309                                         uvB = new UV(0, 1);
310                                         uvA = new UV(1, 1);
311                                 }
312                                 face = new Face(a, b, c, _material, uvA, uvB, uvC);
313                                 mesh.addFace(face);
314                                 face = new Face(c, d, a, _material, uvC, uvD, uvA);
315                                 mesh.addFace(face);
316                                
317                                 if (properties["mirror"] == "1") {
318                                         mirrorAxis = parseInt(properties["mirror_axis"]);
319                                         a = mirrorVertex(a, mirrorAxis);
320                                         b = mirrorVertex(b, mirrorAxis);
321                                         c = mirrorVertex(c, mirrorAxis);
322                                         d = mirrorVertex(d, mirrorAxis);
323                                         vertices.push(a);
324                                         vertices.push(b);
325                                         vertices.push(c);
326                                         vertices.push(d);
327                                         face = new Face(c, b, a, _material, uvC, uvB, uvA);
328                                         mesh.addFace(face);
329                                         face = new Face(a, d, c, _material, uvA, uvD, uvC);
330                                         mesh.addFace(face);
331                                 }
332                         }
333                 }
334                
335                 private static function mirrorVertex(v:Vertex, axis:int):Vertex {
336                         return new Vertex(
337                                 ((axis & 1) != 0) ? -v.x : v.x,
338                                 ((axis & 2) != 0) ? -v.y : v.y,
339                                 ((axis & 4) != 0) ? -v.z : v.z);
340                 }
341                
342                 private static function getChunkLine(lines:Array, chunkName:String, startLine:int = 0):int {
343                         for (var i:uint = startLine; i < lines.length; ++i) {
344                                 if (lines[i].indexOf(chunkName) != -1) {
345                                         return int(i);
346                                 }
347                         }
348                         return -1;
349                 }
350                
351                 private static function getParam(line:String, paramName:String):String {
352                         var prefix:String = paramName + "(";
353                         var prefixLen:int = prefix.length;
354                        
355                         var begin:int = line.indexOf(prefix, 0);
356                         if (begin == -1) {
357                                 return null;
358                         }
359                         var end:int = line.indexOf(")", begin + prefixLen);
360                         if (end == -1){
361                                 return null;
362                         }
363                         return line.substring(begin + prefixLen, end);
364                 }
365         }
366 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。