PageRenderTime 70ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/away3d/loaders/parsers/AWD2Parser.as

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