PageRenderTime 398ms CodeModel.GetById 92ms app.highlight 77ms RepoModel.GetById 174ms app.codeStats 0ms

/src/away3d/loaders/parsers/AWD1Parser.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 429 lines | 310 code | 83 blank | 36 comment | 97 complexity | fe872da08239993d4b2f48fca7da1162 MD5 | raw file
  1package away3d.loaders.parsers
  2{
  3	import flash.geom.Matrix3D;
  4	import flash.net.URLRequest;
  5	import flash.utils.ByteArray;
  6	
  7	import away3d.arcane;
  8	import away3d.containers.ObjectContainer3D;
  9	import away3d.core.base.CompactSubGeometry;
 10	import away3d.core.base.Geometry;
 11	import away3d.entities.Mesh;
 12	import away3d.loaders.misc.ResourceDependency;
 13	import away3d.loaders.parsers.utils.ParserUtil;
 14	import away3d.materials.TextureMaterial;
 15	import away3d.materials.TextureMultiPassMaterial;
 16	import away3d.materials.utils.DefaultMaterialManager;
 17	import away3d.textures.Texture2DBase;
 18	
 19	use namespace arcane;
 20	
 21	/**
 22	 * AWD1Parser provides a parser for the AWD data type. The version 1.0 in ascii. Usually generated by Prefab3D 1.x and Away3D engine exporters.
 23	 */
 24	public class AWD1Parser extends ParserBase
 25	{
 26		private const LIMIT:uint = 65535;
 27		
 28		private var _textData:String;
 29		private var _startedParsing:Boolean;
 30		private var _objs:Array;
 31		private var _geos:Array;
 32		private var _oList:Array;
 33		private var _aC:Array;
 34		private var _dline:Array;
 35		private var _container:ObjectContainer3D;
 36		private var _meshList:Vector.<Mesh>;
 37		private var _inited:Boolean;
 38		private var _uvs:Array;
 39		private var _charIndex:uint;
 40		private var _oldIndex:uint;
 41		private var _stringLength:uint;
 42		private var _state:String = "";
 43		private var _buffer:uint = 0;
 44		private var _isMesh:Boolean;
 45		private var _isMaterial:Boolean;
 46		private var _id:uint;
 47		
 48		/**
 49		 * Creates a new AWD1Parser object.
 50		 * @param uri The url or id of the data or file to be parsed.
 51		 * @param extra The holder for extra contextual data that the parser might need.
 52		 */
 53		
 54		public function AWD1Parser()
 55		{
 56			super(ParserDataFormat.PLAIN_TEXT);
 57		}
 58		
 59		/**
 60		 * Indicates whether or not a given file extension is supported by the parser.
 61		 * @param extension The file extension of a potential file to be parsed.
 62		 * @return Whether or not the given file type is supported.
 63		 */
 64		public static function supportsType(extension:String):Boolean
 65		{
 66			extension = extension.toLowerCase();
 67			return extension == "awd";
 68		}
 69		
 70		/**
 71		 * Tests whether a data block can be parsed by the parser.
 72		 * @param data The data block to potentially be parsed.
 73		 * @return Whether or not the given data is supported.
 74		 */
 75		public static function supportsData(data:*):Boolean
 76		{
 77			var ba:ByteArray;
 78			var str1:String;
 79			var str2:String;
 80			var readLength:Number = 100;
 81			
 82			ba = ParserUtil.toByteArray(data);
 83			
 84			if (ba) {
 85				if (ba.length<100)
 86					readLength = ba.length;
 87					
 88				ba.position = 0;
 89				str1 = ba.readUTFBytes(2);
 90				str2 = ba.readUTFBytes(readLength);
 91			} else {
 92				str1 = (data is String)? String(data).substr(0, 5) : null;
 93				str2 = (data is String)? String(data).substr(0, readLength) : null;
 94			}
 95			if ((str1 == '//') && (str2.indexOf("#v:") != -1))
 96				return true;
 97			
 98			return false;
 99		}
100		
101		/**
102		 * @inheritDoc
103		 */
104		override arcane function resolveDependency(resourceDependency:ResourceDependency):void
105		{
106			if (resourceDependency.assets.length != 1)
107				return;
108			
109			var asset:Texture2DBase = resourceDependency.assets[0] as Texture2DBase;
110			var m:Mesh = retrieveMeshFromID(resourceDependency.id);
111			
112			if (m && asset) {
113				if (materialMode < 2)
114					TextureMaterial(m.material).texture = asset;
115				else
116					TextureMultiPassMaterial(m.material).texture = asset;
117				
118			}
119		}
120		
121		/**
122		 * @inheritDoc
123		 */
124		override arcane function resolveDependencyFailure(resourceDependency:ResourceDependency):void
125		{
126			//missing load for resourceDependency.id;
127		}
128		
129		/**
130		 * @inheritDoc
131		 */
132		protected override function proceedParsing():Boolean
133		{
134			var line:String;
135			var creturn:String = String.fromCharCode(10);
136			
137			if (!_startedParsing) {
138				_textData = getTextData();
139				_startedParsing = true;
140			}
141			
142			if (_textData.indexOf("#t:bsp") != -1)
143				throw new Error("AWD1 holding BSP information is not supported");
144			
145			if (_textData.indexOf(creturn) == -1 || _textData.indexOf(creturn) > 200)
146				creturn = String.fromCharCode(13);
147			
148			if (!_inited) {
149				_inited = true;
150				_meshList = new Vector.<Mesh>();
151				_stringLength = _textData.length;
152				_charIndex = _textData.indexOf(creturn, 0);
153				_oldIndex = _charIndex;
154				_objs = [];
155				_geos = [];
156				_oList = [];
157				_dline = [];
158				_aC = [];
159				
160				_container = new ObjectContainer3D();
161			}
162			
163			var cont:ObjectContainer3D;
164			var i:uint;
165			var oData:Object;
166			var m:Matrix3D;
167			
168			while (_charIndex < _stringLength && hasTime()) {
169				
170				_charIndex = _textData.indexOf(creturn, _oldIndex);
171				
172				if (_charIndex == -1)
173					_charIndex = _stringLength;
174				
175				line = _textData.substring(_oldIndex, _charIndex);
176				
177				if (_charIndex != _stringLength)
178					_oldIndex = _charIndex + 1;
179				
180				if (line.substring(0, 1) == "#" && _state != line.substring(0, 2)) {
181					_state = line.substring(0, 2);
182					_id = 0;
183					_buffer = 0;
184					//unused in f11
185					if (_state == "#v")
186						line.substring(3, line.length - 1);
187					
188					if (_state == "#f")
189						_isMaterial = (parseInt(line.substring(3, 4)) == 2) as Boolean;
190					
191					if (_state == "#t")
192						_isMesh = (line.substring(3, 7) == "mesh");
193					
194					continue;
195				}
196				
197				_dline = line.split(",");
198				
199				if (_dline.length <= 1 && !(_state == "#m" || _state == "#d"))
200					continue;
201				
202				if (_state == "#o") {
203					if (_buffer == 0) {
204						_id = _dline[0];
205						m = new Matrix3D(Vector.<Number>([parseFloat(_dline[1]), parseFloat(_dline[5]), parseFloat(_dline[9]), 0, parseFloat(_dline[2]), parseFloat(_dline[6]), parseFloat(_dline[10]), 0, parseFloat(_dline[3]), parseFloat(_dline[7]), parseFloat(_dline[11]), 0, parseFloat(_dline[4]), parseFloat(_dline[8]), parseFloat(_dline[12]), 1]));
206						
207						++_buffer;
208					} else {
209						
210						//legacy properties left here in case of debug needs
211						oData = {name:(_dline[0] == "")? "m_" + _id : _dline[0],
212								transform:m,
213								//pivotPoint:new Vector3D(parseFloat(_dline[1]), parseFloat(_dline[2]), parseFloat(_dline[3])),
214								container:parseInt(_dline[4]),
215								bothSides:(_dline[5] == "true")? true : false,
216								//ownCanvas:(_dline[6] == "true")? true : false,
217								//pushfront:(_dline[7] == "true")? true : false,
218								//pushback:(_dline[8] == "true")? true : false,
219								x:parseFloat(_dline[9]),
220								y:parseFloat(_dline[10]),
221								z:parseFloat(_dline[11]),
222								
223								material:(_isMaterial && _dline[12] != null && _dline[12] != "")? _dline[12] : null};
224						_objs.push(oData);
225						_buffer = 0;
226					}
227				}
228				
229				if (_state == "#d") {
230					
231					switch (_buffer) {
232						case 0:
233							_id = _geos.length;
234							_geos.push({});
235							++_buffer;
236							_geos[_id].aVstr = line.substring(2, line.length);
237							break;
238						
239						case 1:
240							_geos[_id].aUstr = line.substring(2, line.length);
241							_geos[_id].aV = read(_geos[_id].aVstr).split(",");
242							_geos[_id].aU = read(_geos[_id].aUstr).split(",");
243							++_buffer;
244							break;
245						
246						case 2:
247							_geos[_id].f = line.substring(2, line.length);
248							_objs[_id].geo = _geos[_id];
249							_buffer = 0;
250					}
251					
252				}
253				
254				if (_state == "#c" && !_isMesh) {
255					
256					_id = parseInt(_dline[0]);
257					cont = (_aC.length == 0)? _container : new ObjectContainer3D();
258					m = new Matrix3D(Vector.<Number>([parseFloat(_dline[1]), parseFloat(_dline[5]), parseFloat(_dline[9]), 0, parseFloat(_dline[2]), parseFloat(_dline[6]), parseFloat(_dline[10]), 0, parseFloat(_dline[3]), parseFloat(_dline[7]), parseFloat(_dline[11]), 0, parseFloat(_dline[4]), parseFloat(_dline[8]), parseFloat(_dline[12]), 1]));
259					
260					cont.transform = m;
261					cont.name = (_dline[13] == "null" || _dline[13] == undefined)? "cont_" + _id : _dline[13];
262					
263					_aC.push(cont);
264					
265					if (cont != _container)
266						_aC[0].addChild(cont);
267					
268				}
269			}
270			
271			if (_charIndex >= _stringLength) {
272				var ref:Object;
273				var mesh:Mesh;
274				
275				for (i = 0; i < _objs.length; ++i) {
276					ref = _objs[i];
277					if (ref && ref.geo) {
278						mesh = new Mesh(new Geometry(), null);
279						mesh.name = ref.name;
280						_meshList.push(mesh);
281						
282						if (ref.container != -1 && !_isMesh)
283							_aC[ref.container].addChild(mesh);
284						
285						mesh.transform = ref.transform;
286						if (materialMode < 2)
287							mesh.material = new TextureMaterial(DefaultMaterialManager.getDefaultTexture());
288						else
289							mesh.material = new TextureMultiPassMaterial(DefaultMaterialManager.getDefaultTexture());
290						
291						mesh.material.bothSides = Boolean(ref.bothSides);
292						
293						if (ref.material && ref.material != "")
294							addDependency(ref.name, new URLRequest(ref.material));
295						
296						mesh.material.name = ref.name;
297						
298						if (ref.material && ref.material != "")
299							addDependency(ref.name, new URLRequest(ref.material));
300						
301						parseFacesToMesh(ref.geo, mesh);
302						
303						finalizeAsset(mesh);
304					}
305				}
306				_objs = _geos = _oList = _aC = _uvs = null;
307				
308				// TODO: Don't just return the container. Return assets one by one
309				finalizeAsset(_container);
310				
311				return PARSING_DONE;
312			}
313			
314			return MORE_TO_PARSE;
315		}
316		
317		private function parseFacesToMesh(geo:Object, mesh:Mesh):void
318		{
319			var j:int;
320			var av:Array;
321			var au:Array;
322			
323			var aRef:Array;
324			var mRef:Array;
325			
326			var vertices:Vector.<Number> = new Vector.<Number>();
327			var indices:Vector.<uint> = new Vector.<uint>();
328			var uvs:Vector.<Number> = new Vector.<Number>();
329			var index:uint;
330			var vindex:uint;
331			var uindex:uint;
332			
333			aRef = geo.f.split(",");
334			if (geo.m)
335				mRef = geo.m.split(",");
336			
337			var sub_geom:CompactSubGeometry;
338			var geom:Geometry = mesh.geometry;
339			
340			for (j = 0; j < aRef.length; j += 6) {
341				
342				if (indices.length + 3 > LIMIT) {
343					sub_geom = new CompactSubGeometry();
344					sub_geom.updateIndexData(indices);
345					sub_geom.fromVectors(vertices, uvs, null, null);
346					geom.addSubGeometry(sub_geom);
347					
348					vertices = new Vector.<Number>();
349					indices = new Vector.<uint>();
350					uvs = new Vector.<Number>();
351					vindex = index = uindex = 0;
352				}
353				
354				indices[vindex] = vindex;
355				vindex++;
356				indices[vindex] = vindex;
357				vindex++;
358				indices[vindex] = vindex;
359				vindex++;
360				
361				//face is inverted compared to f10 awd generator
362				av = geo.aV[parseInt(aRef[j + 1], 16)].split("/");
363				vertices[index++] = parseFloat(av[0]);
364				vertices[index++] = parseFloat(av[1]);
365				vertices[index++] = parseFloat(av[2]);
366				
367				av = geo.aV[parseInt(aRef[j], 16)].split("/");
368				vertices[index++] = parseFloat(av[0]);
369				vertices[index++] = parseFloat(av[1]);
370				vertices[index++] = parseFloat(av[2]);
371				
372				av = geo.aV[parseInt(aRef[j + 2], 16)].split("/");
373				vertices[index++] = parseFloat(av[0]);
374				vertices[index++] = parseFloat(av[1]);
375				vertices[index++] = parseFloat(av[2]);
376				
377				au = geo.aU[parseInt(aRef[j + 4], 16)].split("/");
378				uvs[uindex++] = parseFloat(au[0]);
379				uvs[uindex++] = 1 - parseFloat(au[1]);
380				
381				au = geo.aU[parseInt(aRef[j + 3], 16)].split("/");
382				uvs[uindex++] = parseFloat(au[0]);
383				uvs[uindex++] = 1 - parseFloat(au[1]);
384				
385				au = geo.aU[parseInt(aRef[j + 5], 16)].split("/");
386				uvs[uindex++] = parseFloat(au[0]);
387				uvs[uindex++] = 1 - parseFloat(au[1]);
388			}
389			
390			sub_geom = new CompactSubGeometry();
391			sub_geom.updateIndexData(indices);
392			sub_geom.fromVectors(vertices, uvs, null, null);
393			geom.addSubGeometry(sub_geom);
394		}
395		
396		private function retrieveMeshFromID(id:String):Mesh
397		{
398			for (var i:int = 0; i < _meshList.length; ++i) {
399				if (Mesh(_meshList[i]).name == id)
400					return Mesh(_meshList[i]);
401			}
402			
403			return null;
404		}
405		
406		private function read(str:String):String
407		{
408			var start:int = 0;
409			var chunk:String;
410			var dec:String = "";
411			var charcount:int = str.length;
412			for (var i:int = 0; i < charcount; ++i) {
413				if (str.charCodeAt(i) >= 44 && str.charCodeAt(i) <= 48)
414					dec += str.substring(i, i + 1);
415				else {
416					start = i;
417					chunk = "";
418					while (str.charCodeAt(i) != 44 && str.charCodeAt(i) != 45 && str.charCodeAt(i) != 46 && str.charCodeAt(i) != 47 && i <= charcount)
419						i++;
420					chunk = "" + parseInt("0x" + str.substring(start, i), 16);
421					dec += chunk;
422					i--;
423				}
424			}
425			return dec;
426		}
427	
428	}
429}