PageRenderTime 174ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Flash/project-needs/src/away3d/loaders/parsers/AWD2Parser.as

https://github.com/adamriggs/leapmotion
ActionScript | 1065 lines | 761 code | 200 blank | 104 comment | 89 complexity | 1ff7dac44267167349ce025279d13ac4 MD5 | raw file
Possible License(s): Apache-2.0
  1. package away3d.loaders.parsers
  2. {
  3. import away3d.materials.utils.DefaultMaterialManager;
  4. import away3d.animators.nodes.UVClipNode;
  5. import flash.display.Sprite;
  6. import away3d.animators.UVAnimationState;
  7. import away3d.animators.data.UVAnimationFrame;
  8. import away3d.animators.SkeletonAnimationState;
  9. import away3d.animators.data.JointPose;
  10. import away3d.animators.data.Skeleton;
  11. import away3d.animators.data.SkeletonJoint;
  12. import away3d.animators.data.SkeletonPose;
  13. import away3d.animators.nodes.SkeletonClipNode;
  14. import away3d.arcane;
  15. import away3d.containers.ObjectContainer3D;
  16. import away3d.core.base.Geometry;
  17. import away3d.core.base.SubGeometry;
  18. import away3d.entities.Mesh;
  19. import away3d.library.assets.IAsset;
  20. import away3d.loaders.misc.ResourceDependency;
  21. import away3d.loaders.parsers.utils.ParserUtil;
  22. import away3d.materials.ColorMaterial;
  23. import away3d.materials.DefaultMaterialBase;
  24. import away3d.materials.MaterialBase;
  25. import away3d.materials.TextureMaterial;
  26. import away3d.textures.BitmapTexture;
  27. import away3d.textures.Texture2DBase;
  28. import flash.geom.Matrix;
  29. import flash.geom.Matrix3D;
  30. import flash.net.URLRequest;
  31. import flash.utils.ByteArray;
  32. import flash.utils.Endian;
  33. use namespace arcane;
  34. /**
  35. * AWDParser provides a parser for the AWD data type.
  36. */
  37. public class AWD2Parser extends ParserBase
  38. {
  39. private var _byteData : ByteArray;
  40. private var _startedParsing : Boolean;
  41. private var _cur_block_id : uint;
  42. private var _blocks : Vector.<AWDBlock>;
  43. private var _version : Array;
  44. private var _compression : uint;
  45. private var _streaming : Boolean;
  46. private var _texture_users : Object = {};
  47. private var _parsed_header : Boolean;
  48. private var _body : ByteArray;
  49. public static const UNCOMPRESSED : uint = 0;
  50. public static const DEFLATE : uint = 1;
  51. public static const LZMA : uint = 2;
  52. public static const AWD_FIELD_INT8 : uint = 1;
  53. public static const AWD_FIELD_INT16 : uint = 2;
  54. public static const AWD_FIELD_INT32 : uint = 3;
  55. public static const AWD_FIELD_UINT8 : uint = 4;
  56. public static const AWD_FIELD_UINT16 : uint = 5;
  57. public static const AWD_FIELD_UINT32 : uint = 6;
  58. public static const AWD_FIELD_FLOAT32 : uint = 7;
  59. public static const AWD_FIELD_FLOAT64 : uint = 8;
  60. public static const AWD_FIELD_BOOL : uint = 21;
  61. public static const AWD_FIELD_COLOR : uint = 22;
  62. public static const AWD_FIELD_BADDR : uint = 23;
  63. public static const AWD_FIELD_STRING : uint = 31;
  64. public static const AWD_FIELD_BYTEARRAY : uint = 32;
  65. public static const AWD_FIELD_VECTOR2x1 : uint = 41;
  66. public static const AWD_FIELD_VECTOR3x1 : uint = 42;
  67. public static const AWD_FIELD_VECTOR4x1 : uint = 43;
  68. public static const AWD_FIELD_MTX3x2 : uint = 44;
  69. public static const AWD_FIELD_MTX3x3 : uint = 45;
  70. public static const AWD_FIELD_MTX4x3 : uint = 46;
  71. public static const AWD_FIELD_MTX4x4 : uint = 47;
  72. /**
  73. * Creates a new AWDParser object.
  74. * @param uri The url or id of the data or file to be parsed.
  75. * @param extra The holder for extra contextual data that the parser might need.
  76. */
  77. public function AWD2Parser()
  78. {
  79. super(ParserDataFormat.BINARY);
  80. _blocks = new Vector.<AWDBlock>();
  81. _blocks[0] = new AWDBlock();
  82. _blocks[0].data = null; // Zero address means null in AWD
  83. _version = [];
  84. }
  85. /**
  86. * Indicates whether or not a given file extension is supported by the parser.
  87. * @param extension The file extension of a potential file to be parsed.
  88. * @return Whether or not the given file type is supported.
  89. */
  90. public static function supportsType(extension : String) : Boolean
  91. {
  92. extension = extension.toLowerCase();
  93. return extension == "awd";
  94. }
  95. /**
  96. * @inheritDoc
  97. */
  98. override arcane function resolveDependency(resourceDependency:ResourceDependency):void
  99. {
  100. if (resourceDependency.assets.length == 1) {
  101. var asset : Texture2DBase = resourceDependency.assets[0] as Texture2DBase;
  102. if (asset) {
  103. var mat : TextureMaterial;
  104. var users : Array;
  105. var block : AWDBlock = _blocks[parseInt(resourceDependency.id)];
  106. // Store finished asset
  107. block.data = asset;
  108. // Reset name of texture to the one defined in the AWD file,
  109. // as opposed to whatever the image parser came up with.
  110. asset.resetAssetPath(block.name, null, true);
  111. // Finalize texture asset to dispatch texture event, which was
  112. // previously suppressed while the dependency was loaded.
  113. finalizeAsset(asset);
  114. users = _texture_users[resourceDependency.id];
  115. for each (mat in users) {
  116. mat.texture = asset;
  117. finalizeAsset(mat);
  118. }
  119. }
  120. }
  121. }
  122. /**
  123. * @inheritDoc
  124. */
  125. override arcane function resolveDependencyFailure(resourceDependency:ResourceDependency):void
  126. {
  127. if (_texture_users.hasOwnProperty(resourceDependency.id)) {
  128. var mat : TextureMaterial;
  129. var users : Array;
  130. var texture : BitmapTexture = DefaultMaterialManager.getDefaultTexture();
  131. users = _texture_users[resourceDependency.id];
  132. for each (mat in users) {
  133. mat.texture = texture;
  134. finalizeAsset(mat);
  135. }
  136. }
  137. }
  138. /**
  139. * Tests whether a data block can be parsed by the parser.
  140. * @param data The data block to potentially be parsed.
  141. * @return Whether or not the given data is supported.
  142. */
  143. public static function supportsData(data : *) : Boolean
  144. {
  145. return (ParserUtil.toString(data, 3)=='AWD');
  146. }
  147. /**
  148. * @inheritDoc
  149. */
  150. protected override function proceedParsing() : Boolean
  151. {
  152. if(!_startedParsing) {
  153. _byteData = getByteData();
  154. _startedParsing = true;
  155. }
  156. if (!_parsed_header) {
  157. _byteData.endian = Endian.LITTLE_ENDIAN;
  158. //TODO: Create general-purpose parseBlockRef(requiredType) (return _blocks[addr] or throw error)
  159. // Parse header and decompress body
  160. parseHeader();
  161. switch (_compression) {
  162. case DEFLATE:
  163. _body = new ByteArray();
  164. _byteData.readBytes(_body, 0, _byteData.bytesAvailable);
  165. _body.uncompress();
  166. break;
  167. case LZMA:
  168. // TODO: Decompress LZMA into _body
  169. dieWithError('LZMA decoding not yet supported in AWD parser.');
  170. break;
  171. case UNCOMPRESSED:
  172. _body = _byteData;
  173. break;
  174. }
  175. _body.endian = Endian.LITTLE_ENDIAN;
  176. _parsed_header = true;
  177. }
  178. while (_body.bytesAvailable > 0 && !parsingPaused && hasTime()) {
  179. parseNextBlock();
  180. }
  181. // Return complete status
  182. if (_body.bytesAvailable==0) {
  183. return PARSING_DONE;
  184. }
  185. else return MORE_TO_PARSE;
  186. }
  187. private function parseHeader() : void
  188. {
  189. var flags : uint;
  190. var body_len : Number;
  191. // Skip magic string and parse version
  192. _byteData.position = 3;
  193. _version[0] = _byteData.readUnsignedByte();
  194. _version[1] = _byteData.readUnsignedByte();
  195. // Parse bit flags and compression
  196. flags = _byteData.readUnsignedShort();
  197. _streaming = (flags & 0x1) == 0x1;
  198. _compression = _byteData.readUnsignedByte();
  199. // Check file integrity
  200. body_len = _byteData.readUnsignedInt();
  201. if (!_streaming && body_len != _byteData.bytesAvailable) {
  202. dieWithError('AWD2 body length does not match header integrity field');
  203. }
  204. }
  205. private function parseNextBlock() : void
  206. {
  207. var block : AWDBlock;
  208. var assetData : IAsset;
  209. var ns : uint, type : uint, flags : uint, len : uint;
  210. _cur_block_id = _body.readUnsignedInt();
  211. ns = _body.readUnsignedByte();
  212. type = _body.readUnsignedByte();
  213. flags = _body.readUnsignedByte();
  214. len = _body.readUnsignedInt();
  215. block = new AWDBlock();
  216. switch (type) {
  217. case 1:
  218. assetData = parseMeshData(len);
  219. break;
  220. case 22:
  221. assetData = parseContainer(len);
  222. break;
  223. case 23:
  224. assetData = parseMeshInstance(len);
  225. break;
  226. case 81:
  227. assetData = parseMaterial(len);
  228. break;
  229. case 82:
  230. assetData = parseTexture(len, block);
  231. break;
  232. case 101:
  233. assetData = parseSkeleton(len);
  234. break;
  235. case 102:
  236. assetData = parseSkeletonPose(len);
  237. break;
  238. case 103:
  239. assetData = parseSkeletonAnimation(len);
  240. break;
  241. case 121:
  242. assetData = parseUVAnimation(len);
  243. break;
  244. default:
  245. //trace('Ignoring block!');
  246. _body.position += len;
  247. break;
  248. }
  249. // Store block reference for later use
  250. _blocks[_cur_block_id] = block;
  251. _blocks[_cur_block_id].data = assetData;
  252. _blocks[_cur_block_id].id = _cur_block_id;
  253. }
  254. private function parseUVAnimation(blockLength : uint) : UVAnimationState
  255. {
  256. // TODO: not used
  257. blockLength = blockLength;
  258. var name : String;
  259. var num_frames : uint;
  260. var frames_parsed : uint;
  261. var props : AWDProperties;
  262. var dummy : Sprite;
  263. var state : UVAnimationState;
  264. var clip : UVClipNode;
  265. name = parseVarStr();
  266. num_frames = _body.readUnsignedShort();
  267. props = parseProperties(null);
  268. clip = new UVClipNode();
  269. state = new UVAnimationState(clip);
  270. frames_parsed = 0;
  271. dummy = new Sprite();
  272. while (frames_parsed < num_frames) {
  273. var mtx : Matrix;
  274. var frame_dur : uint;
  275. var frame : UVAnimationFrame;
  276. // TODO: Replace this with some reliable way to decompose a 2d matrix
  277. mtx = parseMatrix2D();
  278. mtx.scale(100, 100);
  279. dummy.transform.matrix = mtx;
  280. frame_dur = _body.readUnsignedShort();
  281. frame = new UVAnimationFrame(dummy.x*0.01, dummy.y*0.01, dummy.scaleX/100, dummy.scaleY/100, dummy.rotation);
  282. clip.addFrame(frame, frame_dur);
  283. frames_parsed++;
  284. }
  285. // Ignore for now
  286. parseUserAttributes();
  287. finalizeAsset(clip, name);
  288. finalizeAsset(state, name);
  289. return state;
  290. }
  291. private function parseMaterial(blockLength : uint) : MaterialBase
  292. {
  293. // TODO: not used
  294. blockLength = blockLength;
  295. var name : String;
  296. var type : uint;
  297. var props : AWDProperties;
  298. var mat : DefaultMaterialBase;
  299. var attributes : Object;
  300. var finalize : Boolean;
  301. var num_methods : uint;
  302. var methods_parsed : uint;
  303. name = parseVarStr();
  304. type = _body.readUnsignedByte();
  305. num_methods = _body.readUnsignedByte();
  306. // Read material numerical properties
  307. // (1=color, 2=bitmap url, 10=alpha, 11=alpha_blending, 12=alpha_threshold, 13=repeat)
  308. props = parseProperties({ 1:AWD_FIELD_INT32, 2:AWD_FIELD_BADDR,
  309. 10:AWD_FIELD_FLOAT32, 11:AWD_FIELD_BOOL,
  310. 12:AWD_FIELD_FLOAT32, 13:AWD_FIELD_BOOL });
  311. methods_parsed = 0;
  312. while (methods_parsed < num_methods) {
  313. var method_type : uint;
  314. method_type = _body.readUnsignedShort();
  315. parseProperties(null);
  316. parseUserAttributes();
  317. }
  318. attributes = parseUserAttributes();
  319. if (type == 1) { // Color material
  320. var color : uint;
  321. color = props.get(1, 0xcccccc);
  322. mat = new ColorMaterial(color, props.get(10, 1.0));
  323. }
  324. else if (type == 2) { // Bitmap material
  325. //TODO: not used
  326. //var bmp : BitmapData;
  327. var texture : Texture2DBase;
  328. var tex_addr : uint;
  329. tex_addr = props.get(2, 0);
  330. texture = _blocks[tex_addr].data;
  331. // If bitmap asset has already been loaded
  332. if (texture) {
  333. mat = new TextureMaterial(texture);
  334. TextureMaterial(mat).alphaBlending = props.get(11, false);
  335. TextureMaterial(mat).alpha = props.get(10, 1.0);
  336. finalize = true;
  337. }
  338. else {
  339. // No bitmap available yet. Material will be finalized
  340. // when texture finishes loading.
  341. mat = new TextureMaterial(null);
  342. if (tex_addr > 0)
  343. _texture_users[tex_addr.toString()].push(mat);
  344. finalize = false;
  345. }
  346. }
  347. mat.extra = attributes;
  348. mat.alphaThreshold = props.get(12, 0.0);
  349. mat.repeat = props.get(13, false);
  350. if (finalize) {
  351. finalizeAsset(mat, name);
  352. }
  353. return mat;
  354. }
  355. private function parseTexture(blockLength : uint, block : AWDBlock) : Texture2DBase
  356. {
  357. // TODO: not used
  358. blockLength = blockLength;
  359. var type : uint;
  360. var data_len : uint;
  361. var asset : Texture2DBase;
  362. block.name = parseVarStr();
  363. type = _body.readUnsignedByte();
  364. data_len = _body.readUnsignedInt();
  365. _texture_users[_cur_block_id.toString()] = [];
  366. // External
  367. if (type == 0) {
  368. var url : String;
  369. url = _body.readUTFBytes(data_len);
  370. addDependency(_cur_block_id.toString(), new URLRequest(url), false, null, true);
  371. }
  372. else {
  373. var data : ByteArray;
  374. // TODO: not used
  375. // var loader : Loader;
  376. data = new ByteArray();
  377. _body.readBytes(data, 0, data_len);
  378. addDependency(_cur_block_id.toString(), null, false, data, true);
  379. }
  380. // Ignore for now
  381. parseProperties(null);
  382. parseUserAttributes();
  383. // TODO: Don't do this. Get texture properly
  384. /*
  385. finalizeAsset(asset, name);
  386. */
  387. pauseAndRetrieveDependencies();
  388. return asset;
  389. }
  390. private function parseSkeleton(blockLength : uint) : Skeleton
  391. {
  392. // TODO: not used
  393. blockLength = blockLength;
  394. var name : String;
  395. var num_joints : uint;
  396. var joints_parsed : uint;
  397. var skeleton : Skeleton;
  398. name = parseVarStr();
  399. num_joints = _body.readUnsignedShort();
  400. skeleton = new Skeleton();
  401. // Discard properties for now
  402. parseProperties(null);
  403. joints_parsed = 0;
  404. while (joints_parsed < num_joints) {
  405. // TODO: not used
  406. // var parent_id : uint;
  407. // TODO: not used
  408. //var joint_name : String;
  409. var joint : SkeletonJoint;
  410. var ibp : Matrix3D;
  411. // Ignore joint id
  412. _body.readUnsignedShort();
  413. joint = new SkeletonJoint();
  414. joint.parentIndex = _body.readUnsignedShort() -1; // 0=null in AWD
  415. joint.name = parseVarStr();
  416. ibp = parseMatrix3D();
  417. joint.inverseBindPose = ibp.rawData;
  418. // Ignore joint props/attributes for now
  419. parseProperties(null);
  420. parseUserAttributes();
  421. skeleton.joints.push(joint);
  422. joints_parsed++;
  423. }
  424. // Discard attributes for now
  425. parseUserAttributes();
  426. finalizeAsset(skeleton, name);
  427. return skeleton;
  428. }
  429. private function parseSkeletonPose(blockLength : uint) : SkeletonPose
  430. {
  431. // TODO: not used
  432. blockLength = blockLength;
  433. var name : String;
  434. var pose : SkeletonPose;
  435. var num_joints : uint;
  436. var joints_parsed : uint;
  437. name = parseVarStr();
  438. num_joints = _body.readUnsignedShort();
  439. // Ignore properties for now
  440. parseProperties(null);
  441. pose = new SkeletonPose();
  442. joints_parsed = 0;
  443. while (joints_parsed < num_joints) {
  444. var joint_pose : JointPose;
  445. var has_transform : uint;
  446. joint_pose = new JointPose();
  447. has_transform = _body.readUnsignedByte();
  448. if (has_transform == 1) {
  449. // TODO: not used
  450. // var mtx0 : Matrix3D;
  451. var mtx_data : Vector.<Number> = parseMatrix43RawData();
  452. var mtx : Matrix3D = new Matrix3D(mtx_data);
  453. joint_pose.orientation.fromMatrix(mtx);
  454. joint_pose.translation.copyFrom(mtx.position);
  455. pose.jointPoses[joints_parsed] = joint_pose;
  456. }
  457. joints_parsed++;
  458. }
  459. // Skip attributes for now
  460. parseUserAttributes();
  461. finalizeAsset(pose, name);
  462. return pose;
  463. }
  464. private function parseSkeletonAnimation(blockLength : uint) : SkeletonAnimationState
  465. {
  466. // TODO: not used
  467. blockLength = blockLength;
  468. var name : String;
  469. var num_frames : uint;
  470. var frames_parsed : uint;
  471. // TODO: not used
  472. //var frame_rate : uint;
  473. var frame_dur : Number;
  474. name = parseVarStr();
  475. var clip : SkeletonClipNode = new SkeletonClipNode();
  476. var state : SkeletonAnimationState = new SkeletonAnimationState(clip);
  477. num_frames = _body.readUnsignedShort();
  478. // Ignore properties for now (none in spec)
  479. parseProperties(null);
  480. frames_parsed = 0;
  481. while (frames_parsed < num_frames) {
  482. var pose_addr : uint;
  483. //TODO: Check for null?
  484. pose_addr = _body.readUnsignedInt();
  485. frame_dur = _body.readUnsignedShort();
  486. clip.addFrame(_blocks[pose_addr].data as SkeletonPose, frame_dur);
  487. frames_parsed++;
  488. }
  489. // Ignore attributes for now
  490. parseUserAttributes();
  491. finalizeAsset(state, name);
  492. return state;
  493. }
  494. private function parseContainer(blockLength : uint) : ObjectContainer3D
  495. {
  496. // TODO: not used
  497. blockLength = blockLength;
  498. var name : String;
  499. var par_id : uint;
  500. var mtx : Matrix3D;
  501. var ctr : ObjectContainer3D;
  502. var parent : ObjectContainer3D;
  503. par_id = _body.readUnsignedInt();
  504. mtx = parseMatrix3D();
  505. name = parseVarStr();
  506. ctr = new ObjectContainer3D();
  507. ctr.transform = mtx;
  508. parent = _blocks[par_id].data as ObjectContainer3D;
  509. if (parent) {
  510. parent.addChild(ctr);
  511. }
  512. parseProperties(null);
  513. ctr.extra = parseUserAttributes();
  514. finalizeAsset(ctr, name);
  515. return ctr;
  516. }
  517. private function parseMeshInstance(blockLength : uint) : Mesh
  518. {
  519. // TODO: not used
  520. blockLength = blockLength;
  521. var name : String;
  522. var mesh : Mesh, geom : Geometry;
  523. var par_id : uint, data_id : uint;
  524. var mtx : Matrix3D;
  525. var materials : Vector.<MaterialBase>;
  526. var num_materials : uint;
  527. var materials_parsed : uint;
  528. var parent : ObjectContainer3D;
  529. par_id = _body.readUnsignedInt();
  530. mtx = parseMatrix3D();
  531. name = parseVarStr();
  532. data_id = _body.readUnsignedInt();
  533. geom = _blocks[data_id].data as Geometry;
  534. materials = new Vector.<MaterialBase>();
  535. num_materials = _body.readUnsignedShort();
  536. materials_parsed = 0;
  537. while (materials_parsed < num_materials) {
  538. var mat_id : uint;
  539. mat_id = _body.readUnsignedInt();
  540. materials.push(_blocks[mat_id].data);
  541. materials_parsed++;
  542. }
  543. mesh = new Mesh(geom, null);
  544. mesh.transform = mtx;
  545. // Add to parent if one exists
  546. parent = _blocks[par_id].data as ObjectContainer3D;
  547. if (parent) {
  548. parent.addChild(mesh);
  549. }
  550. if (materials.length >= 1 && mesh.subMeshes.length == 1) {
  551. mesh.material = materials[0];
  552. }
  553. else if (materials.length > 1) {
  554. var i : uint;
  555. // Assign each sub-mesh in the mesh a material from the list. If more sub-meshes
  556. // than materials, repeat the last material for all remaining sub-meshes.
  557. for (i=0; i<mesh.subMeshes.length; i++) {
  558. mesh.subMeshes[i].material = materials[Math.min(materials.length-1, i)];
  559. }
  560. }
  561. // Ignore for now
  562. parseProperties(null);
  563. mesh.extra = parseUserAttributes();
  564. finalizeAsset(mesh, name);
  565. return mesh;
  566. }
  567. private function parseMeshData(blockLength : uint) : Geometry
  568. {
  569. var name : String;
  570. var geom : Geometry;
  571. var num_subs : uint;
  572. var subs_parsed : uint;
  573. var props : AWDProperties;
  574. var bsm : Matrix3D;
  575. // Read name and sub count
  576. name = parseVarStr();
  577. num_subs = _body.readUnsignedShort();
  578. // Read optional properties
  579. props = parseProperties({ 1:AWD_FIELD_MTX4x4 });
  580. geom = new Geometry();
  581. // Loop through sub meshes
  582. subs_parsed = 0;
  583. while (subs_parsed < num_subs) {
  584. var i : uint;
  585. var sm_len : uint, sm_end : uint;
  586. var sub_geoms : Vector.<SubGeometry>;
  587. var w_indices : Vector.<Number>;
  588. var weights : Vector.<Number>;
  589. sm_len = _body.readUnsignedInt();
  590. sm_end = _body.position + sm_len;
  591. // Ignore for now
  592. parseProperties(null);
  593. // Loop through data streams
  594. while (_body.position < sm_end) {
  595. var idx : uint = 0;
  596. var str_ftype : uint;
  597. var str_type : uint, str_len : uint, str_end : uint;
  598. // Type, field type, length
  599. str_type = _body.readUnsignedByte();
  600. str_ftype = _body.readUnsignedByte();
  601. str_len = _body.readUnsignedInt();
  602. str_end = _body.position + str_len;
  603. var x:Number, y:Number, z:Number;
  604. if (str_type == 1) {
  605. var verts : Vector.<Number> = new Vector.<Number>();
  606. while (_body.position < str_end) {
  607. // TODO: Respect stream field type
  608. x = _body.readFloat();
  609. y = _body.readFloat();
  610. z = _body.readFloat();
  611. verts[idx++] = x;
  612. verts[idx++] = y;
  613. verts[idx++] = z;
  614. }
  615. }
  616. else if (str_type == 2) {
  617. var indices : Vector.<uint> = new Vector.<uint>();
  618. while (_body.position < str_end) {
  619. // TODO: Respect stream field type
  620. indices[idx++] = _body.readUnsignedShort();
  621. }
  622. }
  623. else if (str_type == 3) {
  624. var uvs : Vector.<Number> = new Vector.<Number>();
  625. while (_body.position < str_end) {
  626. // TODO: Respect stream field type
  627. uvs[idx++] = _body.readFloat();
  628. }
  629. }
  630. else if (str_type == 4) {
  631. var normals : Vector.<Number> = new Vector.<Number>();
  632. while (_body.position < str_end) {
  633. // TODO: Respect stream field type
  634. normals[idx++] = _body.readFloat();
  635. }
  636. }
  637. else if (str_type == 6) {
  638. w_indices = new Vector.<Number>();
  639. while (_body.position < str_end) {
  640. // TODO: Respect stream field type
  641. w_indices[idx++] = _body.readUnsignedShort()*3;
  642. }
  643. }
  644. else if (str_type == 7) {
  645. weights = new Vector.<Number>();
  646. while (_body.position < str_end) {
  647. // TODO: Respect stream field type
  648. weights[idx++] = _body.readFloat();
  649. }
  650. }
  651. else {
  652. _body.position = str_end;
  653. }
  654. }
  655. // Ignore sub-mesh attributes for now
  656. parseUserAttributes();
  657. sub_geoms = constructSubGeometries(verts, indices, uvs, normals, null, weights, w_indices);
  658. for (i=0; i<sub_geoms.length; i++) {
  659. geom.addSubGeometry(sub_geoms[i]);
  660. // TODO: Somehow map in-sub to out-sub indices to enable look-up
  661. // when creating meshes (and their material assignments.)
  662. }
  663. subs_parsed++;
  664. }
  665. parseUserAttributes();
  666. finalizeAsset(geom, name);
  667. return geom;
  668. }
  669. private function parseVarStr() : String
  670. {
  671. var len : uint;
  672. len = _body.readUnsignedShort();
  673. return _body.readUTFBytes(len);
  674. }
  675. // TODO: Improve this by having some sort of key=type dictionary
  676. private function parseProperties(expected : Object) : AWDProperties
  677. {
  678. var list_end : uint;
  679. var list_len : uint;
  680. var props : AWDProperties;
  681. props = new AWDProperties();
  682. list_len = _body.readUnsignedInt();
  683. list_end = _body.position + list_len;
  684. if (expected) {
  685. while (_body.position < list_end) {
  686. var len : uint;
  687. var key : uint;
  688. var type : uint;
  689. key = _body.readUnsignedShort();
  690. len = _body.readUnsignedInt();
  691. if (expected.hasOwnProperty(key)) {
  692. type = expected[key];
  693. props.set(key, parseAttrValue(type, len));
  694. }
  695. else {
  696. _body.position += len;
  697. }
  698. }
  699. }
  700. return props;
  701. }
  702. private function parseUserAttributes() : Object
  703. {
  704. var attributes : Object;
  705. var list_len : uint;
  706. list_len = _body.readUnsignedInt();
  707. if (list_len > 0) {
  708. var list_end : uint;
  709. attributes = {};
  710. list_end = _body.position + list_len;
  711. while (_body.position < list_end) {
  712. var ns_id : uint;
  713. var attr_key : String;
  714. var attr_type : uint;
  715. var attr_len : uint;
  716. var attr_val : *;
  717. // TODO: Properly tend to namespaces in attributes
  718. ns_id = _body.readUnsignedByte();
  719. attr_key = parseVarStr();
  720. attr_type = _body.readUnsignedByte();
  721. attr_len = _body.readUnsignedInt();
  722. switch (attr_type) {
  723. case AWD_FIELD_STRING:
  724. attr_val = _body.readUTFBytes(attr_len);
  725. break;
  726. default:
  727. attr_val = 'unimplemented attribute type '+attr_type;
  728. _body.position += attr_len;
  729. break;
  730. }
  731. attributes[attr_key] = attr_val;
  732. }
  733. }
  734. return attributes;
  735. }
  736. private function parseAttrValue(type : uint, len : uint) : *
  737. {
  738. var elem_len : uint;
  739. var read_func : Function;
  740. switch (type) {
  741. case AWD_FIELD_INT8:
  742. elem_len = 1;
  743. read_func = _body.readByte;
  744. break;
  745. case AWD_FIELD_INT16:
  746. elem_len = 2;
  747. read_func = _body.readShort;
  748. break;
  749. case AWD_FIELD_INT32:
  750. elem_len = 4;
  751. read_func = _body.readInt;
  752. break;
  753. case AWD_FIELD_BOOL:
  754. case AWD_FIELD_UINT8:
  755. elem_len = 1;
  756. read_func = _body.readUnsignedByte;
  757. break;
  758. case AWD_FIELD_UINT16:
  759. elem_len = 2;
  760. read_func = _body.readUnsignedShort;
  761. break;
  762. case AWD_FIELD_UINT32:
  763. case AWD_FIELD_BADDR:
  764. elem_len = 4;
  765. read_func = _body.readUnsignedInt;
  766. break;
  767. case AWD_FIELD_FLOAT32:
  768. elem_len = 4;
  769. read_func = _body.readFloat;
  770. break;
  771. case AWD_FIELD_FLOAT64:
  772. elem_len = 8;
  773. read_func = _body.readDouble;
  774. break;
  775. case AWD_FIELD_VECTOR2x1:
  776. case AWD_FIELD_VECTOR3x1:
  777. case AWD_FIELD_VECTOR4x1:
  778. case AWD_FIELD_MTX3x2:
  779. case AWD_FIELD_MTX3x3:
  780. case AWD_FIELD_MTX4x3:
  781. case AWD_FIELD_MTX4x4:
  782. elem_len = 8;
  783. read_func = _body.readDouble;
  784. break;
  785. }
  786. if (elem_len < len) {
  787. var list : Array;
  788. var num_read : uint;
  789. var num_elems : uint;
  790. list = [];
  791. num_read = 0;
  792. num_elems = len / elem_len;
  793. while (num_read < num_elems) {
  794. list.push(read_func());
  795. num_read++;
  796. }
  797. return list;
  798. }
  799. else {
  800. var val : *;
  801. val = read_func();
  802. return val;
  803. }
  804. }
  805. private function parseMatrix2D() : Matrix
  806. {
  807. var mtx : Matrix;
  808. var mtx_raw : Vector.<Number> = parseMatrix32RawData();
  809. mtx = new Matrix(mtx_raw[0], mtx_raw[1], mtx_raw[2], mtx_raw[3], mtx_raw[4], mtx_raw[5]);
  810. return mtx;
  811. }
  812. private function parseMatrix3D() : Matrix3D
  813. {
  814. return new Matrix3D(parseMatrix43RawData());
  815. }
  816. private function parseMatrix32RawData() : Vector.<Number>
  817. {
  818. var i : uint;
  819. var mtx_raw : Vector.<Number> = new Vector.<Number>(6, true);
  820. for (i=0; i<6; i++)
  821. mtx_raw[i] = _body.readFloat();
  822. return mtx_raw;
  823. }
  824. private function parseMatrix43RawData() : Vector.<Number>
  825. {
  826. var mtx_raw : Vector.<Number> = new Vector.<Number>(16, true);
  827. mtx_raw[0] = _body.readFloat();
  828. mtx_raw[1] = _body.readFloat();
  829. mtx_raw[2] = _body.readFloat();
  830. mtx_raw[3] = 0.0;
  831. mtx_raw[4] = _body.readFloat();
  832. mtx_raw[5] = _body.readFloat();
  833. mtx_raw[6] = _body.readFloat();
  834. mtx_raw[7] = 0.0;
  835. mtx_raw[8] = _body.readFloat();
  836. mtx_raw[9] = _body.readFloat();
  837. mtx_raw[10] = _body.readFloat();
  838. mtx_raw[11] = 0.0;
  839. mtx_raw[12] = _body.readFloat();
  840. mtx_raw[13] = _body.readFloat();
  841. mtx_raw[14] = _body.readFloat();
  842. mtx_raw[15] = 1.0;
  843. return mtx_raw;
  844. }
  845. }
  846. }
  847. internal class AWDBlock
  848. {
  849. public var id : uint;
  850. public var name : String;
  851. public var data : *;
  852. }
  853. internal dynamic class AWDProperties
  854. {
  855. public function set(key : uint, value : *) : void
  856. {
  857. this[key.toString()] = value;
  858. }
  859. public function get(key : uint, fallback : *) : *
  860. {
  861. if (this.hasOwnProperty(key.toString()))
  862. return this[key.toString()];
  863. else return fallback;
  864. }
  865. }