/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

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