/home/lindsay/xeolabs/xeogl-next/xeogl/examples/js/models/XML3DModel.js
API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/examples/js/models/XML3DModel.js

  1. /**
  2. A **XML3DModel** is a {{#crossLink "Model"}}{{/crossLink}} loaded from a <a href="https://en.wikipedia.org/wiki/3DXML" target = "_other">3DXML</a> file.
  3.  
  4. @class XML3DModel
  5. @module xeogl
  6. @submodule models
  7. @constructor
  8. @param [scene] {Scene} Parent {{#crossLink "Scene"}}Scene{{/crossLink}} - creates this XML3DModel in the default
  9. {{#crossLink "Scene"}}Scene{{/crossLink}} when omitted.
  10. @param [cfg] {*} Configs
  11. @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}},
  12. generated automatically when omitted.
  13. @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this XML3D.
  14. @param [cfg.src] {String} Path to a 3DXML file. You can set this to a new file path at any time.
  15. @param [cfg.displayEffect] {String} Display effect to render with: "shadedWithEdges" | "shaded" | "hiddenLinesRemoved" | "hiddenLinesVisible" | "wireframe".
  16. @extends Model
  17. */
  18. (function () {
  19.  
  20. "use strict";
  21.  
  22. xeogl.XML3DModel = xeogl.Model.extend({
  23.  
  24. type: "xeogl.XML3DModel",
  25.  
  26. _init: function (cfg) {
  27. this._super(cfg);
  28.  
  29. /**
  30. * Supported 3DXML schema versions
  31. * @property supportedSchemas
  32. * @type {string[]}
  33. */
  34. this.supportedSchemas = ["4.2"];
  35.  
  36. this._defaultMaterial = new xeogl.MetallicMaterial(this, {
  37. baseColor: [1, 1, 1],
  38. metallic: 0.6,
  39. roughness: 0.6
  40. });
  41.  
  42. // Material shared by all Meshes that have "lines" Geometry
  43. // Overrides whatever material 3DXML would apply.
  44. this._wireframeMaterial = new xeogl.LambertMaterial(this, {
  45. color: [0, 0, 0],
  46. lineWidth: 2
  47. });
  48.  
  49. // EmphasisMaterial used to create solid, hidden-line effect when rendering solid wireframe
  50. this._wireframeGhostMaterial = new xeogl.EmphasisMaterial(this, {
  51. fill: true,
  52. fillColor: [1, 1, 1],
  53. fillAlpha: .8,
  54. //edges: false,
  55. edges: true,
  56. vertices: false
  57. });
  58.  
  59. this._src = null;
  60. this._options = cfg;
  61.  
  62. /**
  63. * Default viewpoint, containing eye, look and up vectors.
  64. * Only defined if found in the 3DXML file.
  65. * @property viewpoint
  66. * @type {Float32Array}
  67. */
  68. this.viewpoint = null;
  69.  
  70. this.src = cfg.src;
  71. this.displayEffect = cfg.displayEffect;
  72. },
  73.  
  74. _props: {
  75.  
  76. /**
  77. Path to a 3DXML file.
  78.  
  79. You can set this to a new file path at any time (except while loading), which will cause the XML3D to load components from
  80. the new file (after first destroying any components loaded from a previous file path).
  81.  
  82. Fires a {{#crossLink "XML3D/loaded:event"}}{{/crossLink}} event when the 3DXML has loaded.
  83.  
  84. @property src
  85. @type String
  86. */
  87. src: {
  88. set: function (value) {
  89. if (!value) {
  90. return;
  91. }
  92. if (!xeogl._isString(value)) {
  93. this.error("Value for 'src' should be a string");
  94. return;
  95. }
  96. if (value === this._src) { // Already loaded this XML3D
  97.  
  98. /**
  99. Fired whenever this XML3D has finished loading components from the 3DXML file
  100. specified by {{#crossLink "XML3D/src:property"}}{{/crossLink}}.
  101. @event loaded
  102. */
  103. this.fire("loaded", true, true);
  104. return;
  105. }
  106. this.destroyAll();
  107. this._src = value;
  108. xeogl.XML3DModel.load(this, this._src, this._options); // Don't need completion callbacks (model fires "loaded" or "error")
  109. },
  110. get: function () {
  111. return this._src;
  112. }
  113. },
  114.  
  115. /**
  116. Display effect to render with: "shadedWithEdges" | "shaded" | "hiddenLinesRemoved" | "hiddenLinesVisible" | "wireframe".
  117.  
  118. @property displayEffect
  119. @default "shadedWithEdges"
  120. @type String
  121. */
  122. displayEffect: {
  123. set: function (displayEffect) {
  124. displayEffect = displayEffect || "shadedWithEdges";
  125. if (this._displayEffect === displayEffect) {
  126. return;
  127. }
  128. this._displayEffect = displayEffect;
  129. var meshes = this.types["xeogl.Mesh"];
  130. if (meshes) {
  131. switch (this._displayEffect) {
  132. case "shadedWithEdges":
  133. this._wireframeMaterial.lineWidth = 2;
  134. for (var id in meshes) {
  135. var mesh = meshes[id];
  136. if (mesh.geometry.primitive !== "lines") {
  137. mesh.visible = true;
  138. mesh.ghosted = false;
  139. mesh.ghostMaterial.fillAlpha = 0.5;
  140. mesh.opacity = 1;
  141. } else {
  142. mesh.visible = true; // Show lines
  143. }
  144. }
  145. break;
  146. case "shaded":
  147. this._wireframeMaterial.lineWidth = 2;
  148. for (var id in meshes) {
  149. var mesh = meshes[id];
  150. if (mesh.geometry.primitive !== "lines") {
  151. mesh.visible = true;
  152. mesh.ghosted = false;
  153. mesh.ghostMaterial.fillAlpha = 0.5;
  154. mesh.opacity = 1;
  155. } else {
  156. mesh.visible = false; // Hide lines
  157. }
  158. }
  159. break;
  160. case "hiddenLinesRemoved":
  161. this._wireframeMaterial.lineWidth = 2;
  162. for (var id in meshes) {
  163. var mesh = meshes[id];
  164. if (mesh.geometry.primitive !== "lines") {
  165. mesh.visible = true;
  166. mesh.ghosted = true;
  167. mesh.ghostMaterial.fillAlpha = 1.0;
  168. mesh.opacity = 1.0;
  169. } else {
  170. mesh.visible = true; // Show lines
  171. }
  172. }
  173. break;
  174. case "hiddenLinesVisible":
  175. this._wireframeMaterial.lineWidth = 1;
  176. for (var id in meshes) {
  177. var mesh = meshes[id];
  178. if (mesh.geometry.primitive !== "lines") {
  179. mesh.visible = true;
  180. mesh.ghosted = false;
  181. mesh.ghostMaterial.fillAlpha = 0.5;
  182. mesh.opacity = 0.5;
  183. } else {
  184. mesh.visible = true; // Show lines
  185. }
  186. }
  187. break;
  188. case "wireframe":
  189. this._wireframeMaterial.lineWidth = 1;
  190. for (var id in meshes) {
  191. var mesh = meshes[id];
  192. if (mesh.geometry.primitive !== "lines") {
  193. mesh.visible = false;
  194. mesh.ghosted = false;
  195. mesh.ghostMaterial.fillAlpha = 0.5;
  196. mesh.opacity = 0.5;
  197. } else {
  198. mesh.visible = true; // Show lines
  199. }
  200. }
  201. break;
  202. }
  203. }
  204. },
  205. get: function () {
  206. return this._displayEffect;
  207. }
  208. }
  209. },
  210.  
  211. _destroy: function () {
  212. this.destroyAll();
  213. }
  214. });
  215.  
  216. /**
  217. * Loads 3DXML from a URL into a {{#crossLink "Model"}}{{/crossLink}}.
  218. *
  219. * @method load
  220. * @static
  221. * @param {Model} model Model to load into.
  222. * @param {String} src Path to 3DXML file.
  223. * @param {Object} options Loading options.
  224. * @param {Function} [ok] Completion callback.
  225. * @param {Function} [error] Error callback.
  226. */
  227. xeogl.XML3DModel.load = function (model, src, options, ok, error) {
  228.  
  229. var spinner = model.scene.canvas.spinner;
  230. spinner.processes++;
  231.  
  232. load3DXML(model, src, options, function () {
  233. spinner.processes--;
  234. xeogl.scheduleTask(function () {
  235. //console.log("3DXML loaded.");
  236. model.fire("loaded", true, true);
  237. });
  238. if (ok) {
  239. ok();
  240. }
  241. },
  242. function (msg) {
  243. spinner.processes--;
  244. model.error(msg);
  245. if (error) {
  246. error(msg);
  247. }
  248. /**
  249. Fired whenever this XML3D fails to load the 3DXML file
  250. specified by {{#crossLink "XML3D/src:property"}}{{/crossLink}}.
  251. @event error
  252. @param msg {String} Description of the error
  253. */
  254. model.fire("error", msg);
  255. },
  256. function (err) {
  257. console.log("Error, Will Robinson: " + err);
  258. });
  259. };
  260.  
  261. var load3DXML = (function () {
  262. return function (model, src, options, ok, error) {
  263. loadZIP(src, function (zip) { // OK
  264. parse3DXML(zip, options, model, ok, error);
  265. },
  266. error);
  267. };
  268. })();
  269.  
  270. var parse3DXML = (function () {
  271.  
  272. return function (zip, options, model, ok) {
  273. var ctx = {
  274. zip: zip,
  275. edgeThreshold: options.edgeThreshold || 20,
  276. materialWorkflow: options.materialWorkflow,
  277. scene: model.scene,
  278. model: model,
  279. info: {
  280. references: {}
  281. },
  282. materials: {}
  283. };
  284. model.scene.loading++; // Disables (re)compilation
  285.  
  286.  
  287. // Now parse 3DXML
  288.  
  289. parseDocument(ctx, function () {
  290. model.scene.loading--; // Re-enables (re)compilation
  291. //console.log("3DXML parsed.");
  292. ok();
  293. });
  294. };
  295.  
  296. function parseDocument(ctx, ok) {
  297. ctx.zip.getFile("Manifest.xml", function (xmlDoc, json) {
  298. var node = json;
  299. var children = node.children;
  300. for (var i = 0, len = children.length; i < len; i++) {
  301. var child = children[i];
  302. switch (child.type) {
  303. case "Manifest":
  304. parseManifest(ctx, child, ok);
  305. break;
  306. }
  307. }
  308. });
  309. }
  310.  
  311. function parseManifest(ctx, manifest, ok) {
  312. var children = manifest.children;
  313. for (var i = 0, len = children.length; i < len; i++) {
  314. var child = children[i];
  315. switch (child.type) {
  316. case "Root":
  317. var rootFileSrc = child.children[0];
  318. ctx.zip.getFile(rootFileSrc, function (xmlDoc, json) {
  319. parseRoot(ctx, json, ok);
  320. });
  321. break;
  322. }
  323. }
  324. }
  325.  
  326. function parseRoot(ctx, node, ok) {
  327. var children = node.children;
  328. for (var i = 0, len = children.length; i < len; i++) {
  329. var child = children[i];
  330. switch (child.type) {
  331. case "Model_3dxml":
  332. parseModel(ctx, child, ok);
  333. break;
  334. }
  335. }
  336. }
  337.  
  338. function parseModel(ctx, node, ok) {
  339. var children = node.children;
  340. for (var i = 0, len = children.length; i < len; i++) {
  341. var child = children[i];
  342. switch (child.type) {
  343. case "Header":
  344. parseHeader(ctx, child);
  345. break;
  346. case "ProductStructure":
  347. parseProductStructure(ctx, child, ok);
  348. break;
  349. case "DefaultView":
  350. parseDefaultView(ctx, child);
  351. break;
  352. }
  353. }
  354. }
  355.  
  356. function parseHeader(ctx, node) {
  357. var children = node.children;
  358. var metaData = {};
  359. for (var i = 0, len = children.length; i < len; i++) {
  360. var child = children[i];
  361. switch (child.type) {
  362. case "SchemaVersion":
  363. metaData.schemaVersion = child.children[0];
  364. if (!isSchemaVersionSupported(ctx, metaData.schemaVersion)) {
  365. ctx.model.error("Schema version not supported: " + metaData.schemaVersion + " - supported versions are: " + ctx.model.supportedSchemas.join(","));
  366. } else {
  367. //ctx.model.log("Parsing schema version: " + metaData.schemaVersion);
  368. }
  369. break;
  370. case "Title":
  371. metaData.title = child.children[0];
  372. break;
  373. case "Author":
  374. metaData.author = child.children[0];
  375. break;
  376. case "Created":
  377. metaData.created = child.children[0];
  378. break;
  379. }
  380. }
  381. ctx.model.meta = metaData;
  382. }
  383.  
  384. function isSchemaVersionSupported(ctx, schemaVersion) {
  385. var supportedSchemas = ctx.model.supportedSchemas;
  386. for (var i = 0, len = supportedSchemas.length; i < len; i++) {
  387. if (schemaVersion === supportedSchemas[i]) {
  388. return true;
  389. }
  390. }
  391. return false;
  392. }
  393.  
  394. function parseProductStructure(ctx, productStructureNode, ok) {
  395.  
  396. parseReferenceReps(ctx, productStructureNode, function (referenceReps) {
  397.  
  398. //----------------------------------------------------------------------------------
  399. // Parse out an intermediate scene DAG representation, that we can then
  400. // recursive descend through to build a xeogl Object hierarchy.
  401. //----------------------------------------------------------------------------------
  402.  
  403. var children = productStructureNode.children;
  404.  
  405. var reference3Ds = {};
  406. var instanceReps = {};
  407. var instance3Ds = {};
  408.  
  409. var rootNode;
  410. var nodes = {};
  411.  
  412. // Map all the elements
  413.  
  414. for (var i = 0, len = children.length; i < len; i++) {
  415. var child = children[i];
  416. switch (child.type) {
  417.  
  418. case "Reference3D":
  419. reference3Ds[child.id] = {
  420. type: "Reference3D",
  421. id: child.id,
  422. name: child.name,
  423. instance3Ds: {},
  424. instanceReps: {}
  425. };
  426. break;
  427.  
  428. case "InstanceRep":
  429. var isAggregatedBy;
  430. var isInstanceOf;
  431. var relativeMatrix;
  432. for (var j = 0, lenj = child.children.length; j < lenj; j++) {
  433. var child2 = child.children[j];
  434. switch (child2.type) {
  435. case "IsAggregatedBy":
  436. isAggregatedBy = child2.children[0];
  437. break;
  438. case "IsInstanceOf":
  439. isInstanceOf = child2.children[0];
  440. break;
  441. }
  442. }
  443. instanceReps[child.id] = {
  444. type: "InstanceRep",
  445. id: child.id,
  446. isAggregatedBy: isAggregatedBy,
  447. isInstanceOf: isInstanceOf,
  448. referenceReps: {}
  449. };
  450. break;
  451.  
  452. case "Instance3D":
  453. var isAggregatedBy;
  454. var isInstanceOf;
  455. var relativeMatrix;
  456. for (var j = 0, lenj = child.children.length; j < lenj; j++) {
  457. var child2 = child.children[j];
  458. switch (child2.type) {
  459. case "IsAggregatedBy":
  460. isAggregatedBy = child2.children[0];
  461. break;
  462. case "IsInstanceOf":
  463. isInstanceOf = child2.children[0];
  464. break;
  465. case "RelativeMatrix":
  466. relativeMatrix = child2.children[0];
  467. break;
  468. }
  469. }
  470. instance3Ds[child.id] = {
  471. type: "Instance3D",
  472. id: child.id,
  473. isAggregatedBy: isAggregatedBy,
  474. isInstanceOf: isInstanceOf,
  475. relativeMatrix: relativeMatrix,
  476. reference3Ds: {}
  477. };
  478. break;
  479. }
  480. }
  481.  
  482. // Connect Reference3Ds to the Instance3Ds they aggregate
  483.  
  484. for (var id in instance3Ds) {
  485. var instance3D = instance3Ds[id];
  486. var reference3D = reference3Ds[instance3D.isAggregatedBy];
  487. if (reference3D) {
  488. reference3D.instance3Ds[instance3D.id] = instance3D;
  489. } else {
  490. alert("foo")
  491. }
  492. }
  493.  
  494. // Connect Instance3Ds to the Reference3Ds they instantiate
  495.  
  496. for (var id in instance3Ds) {
  497. var instance3D = instance3Ds[id];
  498. var reference3D = reference3Ds[instance3D.isInstanceOf];
  499. instance3D.reference3Ds[reference3D.id] = reference3D;
  500. reference3D.instance3D = instance3D;
  501. }
  502.  
  503. // Connect InstanceReps to the ReferenceReps they instantiate
  504.  
  505. for (var id in instanceReps) {
  506. var instanceRep = instanceReps[id];
  507. var referenceRep = referenceReps[instanceRep.isInstanceOf];
  508. if (referenceRep) {
  509. instanceRep.referenceReps[referenceRep.id] = referenceRep;
  510. }
  511. }
  512.  
  513. // Connect Reference3Ds to the InstanceReps they aggregate
  514.  
  515. for (var id in instanceReps) {
  516. var instanceRep = instanceReps[id];
  517. var reference3D = reference3Ds[instanceRep.isAggregatedBy];
  518. if (reference3D) {
  519. reference3D.instanceReps[instanceRep.id] = instanceRep;
  520. }
  521. }
  522.  
  523. // console.log("*****************************************************************************");
  524. // console.log("reference3Ds:\n\n");
  525. // console.log(JSON.stringify(reference3Ds, null, "\t"));
  526. // console.log("*****************************************************************************");
  527.  
  528. function parseReference3D(ctx, reference3D, group) {
  529. //ctx.model.log("parseReference3D( " + reference3D.id + " )");
  530. for (var id in reference3D.instance3Ds) {
  531. parseInstance3D(ctx, reference3D.instance3Ds[id], group);
  532. }
  533. for (var id in reference3D.instanceReps) {
  534. parseInstanceRep(ctx, reference3D.instanceReps[id], group);
  535. }
  536. }
  537.  
  538. function parseInstance3D(ctx, instance3D, group) {
  539. //ctx.model.log("parseInstance3D( " + instance3D.id + " )");
  540.  
  541. if (instance3D.relativeMatrix) {
  542. var matrix = parseFloatArray(instance3D.relativeMatrix, 12);
  543. var translate = [matrix[9], matrix[10], matrix[11]];
  544. var mat3 = matrix.slice(0, 9); // Rotation matrix
  545. var mat4 = xeogl.math.mat3ToMat4(mat3, xeogl.math.identityMat4()); // Convert rotation matrix to 4x4
  546. var childGroup = new xeogl.Group(ctx.model.scene, {
  547. position: translate
  548. });
  549. if (group) {
  550. group.addChild(childGroup);
  551. } else {
  552. ctx.model.addChild(childGroup);
  553. }
  554. group = childGroup;
  555. childGroup = new xeogl.Group(ctx.model.scene, {
  556. matrix: mat4
  557. });
  558. group.addChild(childGroup);
  559. group = childGroup;
  560. } else {
  561. var childGroup = new xeogl.Group(ctx.model.scene, {});
  562. if (group) {
  563. group.addChild(childGroup);
  564. } else {
  565. ctx.model.addChild(childGroup);
  566. }
  567. group = childGroup;
  568. }
  569. for (var id in instance3D.reference3Ds) {
  570. parseReference3D(ctx, instance3D.reference3Ds[id], group);
  571. }
  572. }
  573.  
  574. function parseInstanceRep(ctx, instanceRep, group) {
  575. //ctx.model.log("parseInstanceRep( " + instanceRep.id + " )");
  576. if (instanceRep.referenceReps) {
  577. for (var id in instanceRep.referenceReps) {
  578. var referenceRep = instanceRep.referenceReps[id];
  579. for (var id2 in referenceRep) {
  580. if (id2 === "id") {
  581. continue; // HACK
  582. }
  583. var meshCfg = referenceRep[id2];
  584. var lines = meshCfg.geometry.primitive === "lines";
  585. var material = lines ? ctx.model._wireframeMaterial : (meshCfg.materialId ? ctx.materials[meshCfg.materialId] : null);
  586. var colorize = meshCfg.color;
  587. var mesh = new xeogl.Mesh(ctx.model.scene, {
  588. geometry: meshCfg.geometry,
  589. material: material || ctx.model._defaultMaterial,
  590. colorize: colorize,
  591. ghostMaterial: !lines ? ctx.model._wireframeGhostMaterial : null,
  592. backfaces: false,
  593. quantized: true
  594. });
  595. ctx.model._addComponent(mesh);
  596. if (group) {
  597. group.addChild(mesh);
  598. } else {
  599. ctx.model.addChild(mesh);
  600. }
  601. mesh.colorize = colorize; // HACK: Mesh has inherited model's colorize state, so we need to restore it (we'd better not modify colorize on the model).
  602. }
  603. }
  604. }
  605. }
  606.  
  607. // Find the root Reference3D
  608.  
  609. for (var id in reference3Ds) {
  610. var reference3D = reference3Ds[id];
  611. if (!reference3D.instance3D) {
  612. parseReference3D(ctx, reference3D, null); // HACK: Assuming that root has id == "1"
  613. ok();
  614. return;
  615. }
  616. }
  617.  
  618. alert("No root Reference3D element found in this model - can't load.");
  619.  
  620. ok();
  621. });
  622. }
  623.  
  624. function parseIntArray(str) {
  625. var parts = str.split(" ");
  626. var result = new Int32Array(parts.length);
  627. for (var i = 0; i < parts.length; i++) {
  628. result[i] = parseInt(parts[i]);
  629. }
  630. return result;
  631. }
  632.  
  633. function parseReferenceReps(ctx, node, ok) {
  634. var referenceReps = {};
  635. var children = node.children;
  636. var numToLoad = 0;
  637. for (var i = 0, len = children.length; i < len; i++) {
  638. var child = children[i];
  639. if (child.type === "ReferenceRep") {
  640. numToLoad++;
  641. }
  642. }
  643. for (var i = 0, len = children.length; i < len; i++) {
  644. var child = children[i];
  645. switch (child.type) {
  646. case "ReferenceRep":
  647. if (child.associatedFile) {
  648. var src = stripURN(child.associatedFile);
  649. (function () {
  650. var childId = child.id;
  651. ctx.zip.getFile(src, function (xmlDoc, json) {
  652.  
  653. var materialIds = xmlDoc.getElementsByTagName("MaterialId");
  654.  
  655. loadCATMaterialRefDocuments(ctx, materialIds, function () {
  656.  
  657. // ctx.model.log("reference loaded: " + src);
  658. var referenceRep = {
  659. id: childId
  660. };
  661. parse3DRepDocument(ctx, json, referenceRep);
  662. referenceReps[childId] = referenceRep;
  663. if (--numToLoad === 0) {
  664. console.log("All ReferenceReps loaded.");
  665. ok(referenceReps);
  666. }
  667. });
  668. },
  669. function (error) {
  670. // TODO:
  671. });
  672. })();
  673. }
  674. break;
  675. }
  676. }
  677. }
  678.  
  679.  
  680. function parseDefaultView(ctx, node) {
  681. // ctx.model.log("parseDefaultView");
  682. var children = node.children;
  683. for (var i = 0, len = children.length; i < len; i++) {
  684. var child = children[i];
  685. switch (child.type) {
  686. case "Viewpoint":
  687. var children2 = child.children;
  688. ctx.model.viewpoint = {};
  689. for (var i2 = 0, len2 = children2.length; i2 < len2; i2++) {
  690. var child2 = children2[i];
  691. switch (child2.type) {
  692. case "Position":
  693. ctx.model.viewpoint.eye = parseFloatArray(child2.children[0], 3);
  694. break;
  695. case "Sight":
  696. ctx.model.viewpoint.look = parseFloatArray(child2.children[0], 3);
  697. break;
  698. case "Up":
  699. ctx.model.viewpoint.up = parseFloatArray(child2.children[0], 3);
  700. break;
  701. }
  702. }
  703. break;
  704. case "DefaultViewProperty":
  705. break;
  706. }
  707. }
  708. }
  709.  
  710. function parse3DRepDocument(ctx, node, result) {
  711. // ctx.model.log("parse3DRepDocument");
  712. var children = node.children;
  713. for (var i = 0, len = children.length; i < len; i++) {
  714. var child = children[i];
  715. switch (child.type) {
  716. case "XMLRepresentation":
  717. parseXMLRepresentation(ctx, child, result);
  718. break;
  719. }
  720. }
  721. }
  722.  
  723. function parseXMLRepresentation(ctx, node, result) {
  724. // ctx.model.log("parseXMLRepresentation");
  725. var children = node.children;
  726. for (var i = 0, len = children.length; i < len; i++) {
  727. var child = children[i];
  728. switch (child.type) {
  729. case "Root":
  730. parse3DRepRoot(ctx, child, result);
  731. break;
  732. }
  733. }
  734. }
  735.  
  736. function parse3DRepRoot(ctx, node, result) {
  737. // ctx.model.log("parse3DRepRoot");
  738. switch (node["xsi:type"]) {
  739. case "BagRepType":
  740. break;
  741. case "PolygonalRepType":
  742. break;
  743. }
  744. var children = node.children;
  745. for (var i = 0, len = children.length; i < len; i++) {
  746. var child = children[i];
  747. switch (child.type) {
  748. case "Rep":
  749. parse3DRepRep(ctx, child, result);
  750. break;
  751. }
  752. }
  753. }
  754.  
  755. function parse3DRepRep(ctx, node, result) {
  756. // ctx.model.log("parse3DRep");
  757. switch (node["xsi:type"]) {
  758. case "BagRepType":
  759. break;
  760. case "PolygonalRepType":
  761. break;
  762. }
  763. var meshesResult = {
  764. edgeThreshold: ctx.edgeThreshold || 20
  765. };
  766. var children = node.children;
  767. for (var i = 0, len = children.length; i < len; i++) {
  768. var child = children[i];
  769. switch (child.type) {
  770. case "Rep":
  771. parse3DRepRep(ctx, child, result);
  772. break;
  773. case "Edges":
  774. meshesResult.primitive = "lines";
  775. parseEdges(ctx, child, meshesResult);
  776. break;
  777. case "Faces":
  778. meshesResult.primitive = "triangles";
  779. parseFaces(ctx, child, meshesResult);
  780. break;
  781. case "VertexBuffer":
  782. parseVertexBuffer(ctx, child, meshesResult);
  783. break;
  784. case "SurfaceAttributes":
  785. parseSurfaceAttributes(ctx, child, meshesResult);
  786. break;
  787. }
  788. }
  789. if (meshesResult.positions) {
  790. var geometry = new xeogl.Geometry(ctx.model.scene, meshesResult);
  791. ctx.model._addComponent(geometry);
  792. result[geometry.id] = {
  793. geometry: geometry,
  794. color: meshesResult.color || [1.0, 1.0, 1.0, 1.0],
  795. materialId: meshesResult.materialId
  796. };
  797. }
  798. }
  799.  
  800. function parseEdges(ctx, node, result) {
  801. // ctx.model.log("parseEdges");
  802. result.positions = [];
  803. result.indices = [];
  804. var children = node.children;
  805. for (var i = 0, len = children.length; i < len; i++) {
  806. var child = children[i];
  807. switch (child.type) {
  808. case "Polyline":
  809. parsePolyline(ctx, child, result);
  810. break;
  811. }
  812. }
  813. }
  814.  
  815. function parsePolyline(ctx, node, result) {
  816. //ctx.model.log("parsePolyline");
  817. var vertices = node.vertices;
  818. if (vertices) {
  819. var positions = parseFloatArray(vertices, 3);
  820. if (positions.length > 0) {
  821. var positionsOffset = result.positions.length / 3;
  822. for (var i = 0, len = positions.length; i < len; i++) {
  823. result.positions.push(positions[i]);
  824. }
  825. for (var i = 0, len = (positions.length / 3) - 1; i < len; i++) {
  826. result.indices.push(positionsOffset + i);
  827. result.indices.push(positionsOffset + i + 1);
  828. }
  829. }
  830. }
  831. }
  832.  
  833. function parseFaces(ctx, node, result) {
  834. // ctx.model.log("parseFaces");
  835. var children = node.children;
  836. for (var i = 0, len = children.length; i < len; i++) {
  837. var child = children[i];
  838. switch (child.type) {
  839. case "Face":
  840. parseFace(ctx, child, result);
  841. break;
  842. }
  843. }
  844. }
  845.  
  846. function parseFace(ctx, node, result) {
  847. // ctx.model.log("parseFace");
  848.  
  849. var strips = node.strips;
  850. if (strips) {
  851.  
  852. // Triangle strips
  853.  
  854. var arrays = parseIntArrays(strips);
  855. if (arrays.length > 0) {
  856. result.primitive = "triangles";
  857. var indices = [];
  858. for (var i = 0, len = arrays.length; i < len; i++) {
  859. var array = convertTriangleStrip(arrays[i]);
  860. for (var j = 0, lenj = array.length; j < lenj; j++) {
  861. indices.push(array[j]);
  862. }
  863. }
  864. result.indices = indices; // TODO
  865. }
  866. } else {
  867.  
  868. // Triangle meshes
  869.  
  870. var triangles = node.triangles;
  871. if (triangles) {
  872. result.primitive = "triangles";
  873. result.indices = parseIntArray(triangles);
  874. }
  875. }
  876.  
  877. // Material
  878.  
  879. var children = node.children;
  880. for (var i = 0, len = children.length; i < len; i++) {
  881. var child = children[i];
  882. switch (child.type) {
  883. case "SurfaceAttributes":
  884. parseSurfaceAttributes(ctx, child, result);
  885. break;
  886. }
  887. }
  888. }
  889.  
  890. function convertTriangleStrip(indices) {
  891. var ccw = false;
  892. var indices2 = [];
  893. for (var i = 0, len = indices.length; i < len - 2; i++) {
  894. if (ccw) {
  895. if (i & 1) { //
  896. indices2.push(indices[i]);
  897. indices2.push(indices[i + 1]);
  898. indices2.push(indices[i + 2]);
  899. } else {
  900. indices2.push(indices[i]);
  901. indices2.push(indices[i + 2]);
  902. indices2.push(indices[i + 1]);
  903. }
  904. } else {
  905. if (i & 1) { //
  906. indices2.push(indices[i]);
  907. indices2.push(indices[i + 2]);
  908. indices2.push(indices[i + 1]);
  909. } else {
  910. indices2.push(indices[i]);
  911. indices2.push(indices[i + 1]);
  912. indices2.push(indices[i + 2]);
  913. }
  914. }
  915. }
  916. return indices2;
  917. }
  918.  
  919. function parseVertexBuffer(ctx, node, result) {
  920. var children = node.children;
  921. for (var i = 0, len = children.length; i < len; i++) {
  922. var child = children[i];
  923. switch (child.type) {
  924. case "Positions":
  925. result.positions = parseFloatArray(child.children[0], 3);
  926. break;
  927. case "Normals":
  928. result.normals = parseFloatArray(child.children[0], 3);
  929. break;
  930. case "TextureCoordinates": // TODO: Support dimension and channel?
  931. result.uv = parseFloatArray(child.children[0], 2);
  932. break;
  933. }
  934. }
  935. }
  936.  
  937. function parseIntArrays(str) {
  938. var coordStrings = str.split(",");
  939. var array = [];
  940. for (var i = 0, len = coordStrings.length; i < len; i++) {
  941. var coordStr = coordStrings[i].trim();
  942. if (coordStr.length > 0) {
  943. var elemStrings = coordStr.split(" ");
  944. var arr = new Int16Array(elemStrings.length);
  945. var arrIdx = 0;
  946. for (var j = 0, lenj = elemStrings.length; j < lenj; j++) {
  947. if (elemStrings[j] !== "") {
  948. arr[arrIdx++] = parseInt(elemStrings[j]);
  949. }
  950. }
  951. array.push(arr);
  952. }
  953. }
  954. return array;
  955. }
  956.  
  957. function parseFloatArray(str, numElems) {
  958. str = str.split(",");
  959. var arr = new Float32Array(str.length * numElems);
  960. var arrIdx = 0;
  961. for (var i = 0, len = str.length; i < len; i++) {
  962. var value = str[i];
  963. value = value.split(" ");
  964. for (var j = 0, lenj = value.length; j < lenj; j++) {
  965. if (value[j] !== "") {
  966. arr[arrIdx++] = parseFloat(value[j]);
  967. }
  968. }
  969. }
  970. return arr;
  971. }
  972.  
  973. function parseIntArray(str) {
  974. str = str.split(" ");
  975. var arr = new Int32Array(str.length);
  976. var arrIdx = 0;
  977. for (var i = 0, len = str.length; i < len; i++) {
  978. var value = str[i];
  979. arr[i] = parseInt(value);
  980. }
  981. return arr;
  982. }
  983.  
  984. function parseSurfaceAttributes(ctx, node, result) {
  985. result.color = [1, 1, 1, 1];
  986. var children = node.children;
  987. for (var i = 0, len = children.length; i < len; i++) {
  988. var child = children[i];
  989. switch (child.type) {
  990. case "Color":
  991. result.color[0] = child.red;
  992. result.color[1] = child.green;
  993. result.color[2] = child.blue;
  994. result.color[3] = child.alpha;
  995. break;
  996. case "MaterialApplication":
  997. var children2 = child.children;
  998. for (var j = 0, lenj = children2.length; j < lenj; j++) {
  999. var child2 = children2[j];
  1000. switch (child2.type) {
  1001. case "MaterialId":
  1002. var materialId = getIDFromURI(child2.id);
  1003. var material = ctx.materials[materialId];
  1004. if (!material) {
  1005. ctx.model.error("material not found: " + materialId);
  1006. }
  1007. result.materialId = materialId;
  1008. break;
  1009. }
  1010. }
  1011. break;
  1012. }
  1013. }
  1014. }
  1015. })();
  1016.  
  1017. //----------------------------------------------------------------------------------------------------
  1018. // Materials
  1019. //----------------------------------------------------------------------------------------------------
  1020.  
  1021. function loadCATMaterialRefDocuments(ctx, materialIds, ok) {
  1022. var loaded = {};
  1023.  
  1024. function load(i, done) {
  1025. if (i >= materialIds.length) {
  1026. ok();
  1027. return;
  1028. }
  1029. var materialId = materialIds[i];
  1030. var src = materialId.id;
  1031. var colonIdx = src.lastIndexOf(":");
  1032. if (colonIdx > 0) {
  1033. src = src.substring(colonIdx + 1);
  1034. }
  1035. var hashIdx = src.lastIndexOf("#");
  1036. if (hashIdx > 0) {
  1037. src = src.substring(0, hashIdx);
  1038. }
  1039. if (!loaded[src]) {
  1040. loadCATMaterialRefDocument(ctx, src, function () {
  1041. loaded[src] = true;
  1042. load(i + 1, done);
  1043. });
  1044. } else {
  1045. load(i + 1, done);
  1046. }
  1047. }
  1048.  
  1049. load(0, ok);
  1050. }
  1051.  
  1052. function loadCATMaterialRefDocument(ctx, src, ok) { // Loads CATMaterialRef.3dxml
  1053. ctx.zip.getFile(src, function (xmlDoc, json) {
  1054. parseCATMaterialRefDocument(ctx, json, ok);
  1055. });
  1056. }
  1057.  
  1058. function parseCATMaterialRefDocument(ctx, node, ok) { // Parse CATMaterialRef.3dxml
  1059. // ctx.model.log("parseCATMaterialRefDocument");
  1060. var children = node.children;
  1061. var child;
  1062. for (var i = 0, len = children.length; i < len; i++) {
  1063. child = children[i];
  1064. if (child.type === "Model_3dxml") {
  1065. parseModel_3dxml(ctx, child, ok);
  1066. }
  1067. }
  1068. }
  1069.  
  1070. function parseModel_3dxml(ctx, node, ok) { // Parse CATMaterialRef.3dxml
  1071. // ctx.model.log("parseModel_3dxml");
  1072. var children = node.children;
  1073. var child;
  1074. for (var i = 0, len = children.length; i < len; i++) {
  1075. child = children[i];
  1076. if (child.type === "CATMaterialRef") {
  1077. parseCATMaterialRef(ctx, child, ok);
  1078. }
  1079. }
  1080. }
  1081.  
  1082. function parseCATMaterialRef(ctx, node, ok) {
  1083.  
  1084. // ctx.model.log("parseCATMaterialRef");
  1085.  
  1086. var domainToReferenceMap = {};
  1087. var materials = {};
  1088.  
  1089. var result = {};
  1090. var children = node.children;
  1091. var child;
  1092. var numToLoad = 0;
  1093.  
  1094. for (var j = 0, lenj = children.length; j < lenj; j++) {
  1095. var child2 = children[j];
  1096. switch (child2.type) {
  1097. case "MaterialDomainInstance":
  1098. var isAggregatedBy;
  1099. var isInstanceOf;
  1100. for (var k = 0, lenk = child2.children.length; k < lenk; k++) {
  1101. var child3 = child2.children[k];
  1102. switch (child3.type) {
  1103. case "IsAggregatedBy":
  1104. isAggregatedBy = child3.children[0];
  1105. break;
  1106. case "IsInstanceOf":
  1107. isInstanceOf = child3.children[0];
  1108. break;
  1109. }
  1110. }
  1111. domainToReferenceMap[isInstanceOf] = isAggregatedBy;
  1112. break;
  1113. }
  1114. }
  1115.  
  1116. for (var j = 0, lenj = children.length; j < lenj; j++) {
  1117. var child2 = children[j];
  1118. switch (child2.type) {
  1119. case "MaterialDomain":
  1120. numToLoad++;
  1121. break;
  1122. }
  1123. }
  1124.  
  1125. // Now load them
  1126.  
  1127. for (var j = 0, lenj = children.length; j < lenj; j++) {
  1128. var child2 = children[j];
  1129. switch (child2.type) {
  1130. case "MaterialDomain":
  1131. if (child2.associatedFile) {
  1132. (function () {
  1133. var childId = child2.id;
  1134. var src = stripURN(child2.associatedFile);
  1135. ctx.zip.getFile(src, function (xmlDoc, json) {
  1136. // ctx.model.log("Material def loaded: " + src);
  1137. ctx.materials[domainToReferenceMap[childId]] = parseMaterialDefDocument(ctx, json);
  1138.  
  1139. if (--numToLoad === 0) {
  1140. // console.log("All ReferenceReps loaded.");
  1141. ok();
  1142. }
  1143. },
  1144. function (error) {
  1145. // TODO:
  1146. });
  1147. })();
  1148. }
  1149. break;
  1150. }
  1151. }
  1152. }
  1153.  
  1154. function parseMaterialDefDocument(ctx, node) {
  1155. // ctx.model.log("parseMaterialDefDocumentOsm");
  1156. var children = node.children;
  1157. for (var i = 0, len = children.length; i < len; i++) {
  1158. var child = children[i];
  1159. switch (child.type) {
  1160. case "Osm":
  1161. return parseMaterialDefDocumentOsm(ctx, child);
  1162. break;
  1163. }
  1164. }
  1165. }
  1166.  
  1167. function parseMaterialDefDocumentOsm(ctx, node) {
  1168. // ctx.model.log("parseMaterialDefDocument");
  1169. var children = node.children;
  1170. for (var i = 0, len = children.length; i < len; i++) {
  1171. var child = children[i];
  1172. // ctx.model.log("parseMaterialDefDocument: child.type == " + child.type);
  1173. switch (child.type) {
  1174. case "RenderingRootFeature":
  1175. //..
  1176. break;
  1177. case "Feature":
  1178.  
  1179. if (child.Alias === "RenderingFeature") {
  1180. // Parse the coefficients, then parse the colors, scaling those by their coefficients.
  1181.  
  1182. var coeffs = {};
  1183. var materialCfg = {};
  1184. var children2 = child.children;
  1185. var j;
  1186. var lenj;
  1187. var child2;
  1188. for (j = 0, lenj = children2.length; j < lenj; j++) {
  1189. child2 = children2[j];
  1190. switch (child2.Name) {
  1191. case "AmbientCoef":
  1192. coeffs.ambient = parseFloat(child2.Value);
  1193. break;
  1194. case "DiffuseCoef":
  1195. coeffs.diffuse = parseFloat(child2.Value);
  1196. break;
  1197. case "EmissiveCoef":
  1198. coeffs.emissive = parseFloat(child2.Value);
  1199. break;
  1200. case "SpecularExponent":
  1201. coeffs.specular = parseFloat(child2.Value);
  1202. break;
  1203. }
  1204. }
  1205. for (j = 0, lenj = children2.length; j < lenj; j++) {
  1206. child2 = children2[j];
  1207. switch (child2.Name) {
  1208. case "AmbientColor":
  1209. materialCfg.ambient = parseRGB(child2.Value, coeffs.ambient);
  1210. break;
  1211. case "DiffuseColor":
  1212. materialCfg.diffuse = parseRGB(child2.Value, coeffs.diffuse);
  1213. break;
  1214. case "EmissiveColor":
  1215. materialCfg.emissive = parseRGB(child2.Value, coeffs.emissive);
  1216. break;
  1217. case "SpecularColor":
  1218. materialCfg.specular = parseRGB(child2.Value, coeffs.specular);
  1219. break;
  1220. case "Transparency":
  1221. var alpha = 1.0 - parseFloat(child2.Value); // GOTCHA: Degree of transparency, not degree of opacity
  1222. if (alpha < 1.0) {
  1223. materialCfg.alpha = alpha;
  1224. materialCfg.alphaMode = "blend";
  1225. }
  1226. break;
  1227. }
  1228. }
  1229.  
  1230. var material;
  1231.  
  1232. switch (ctx.materialWorkflow) {
  1233. case "MetallicMaterial":
  1234. material = new xeogl.MetallicMaterial(ctx.model.scene, {
  1235. baseColor: materialCfg.diffuse,
  1236. metallic: 0.7,
  1237. roughness: 0.5,
  1238. emissive: materialCfg.emissive,
  1239. alpha: materialCfg.alpha,
  1240. alphaMode: materialCfg.alphaMode
  1241. });
  1242. break;
  1243.  
  1244. case "SpecularMaterial":
  1245. material = new xeogl.SpecularMaterial(ctx.model.scene, {
  1246. diffuse: materialCfg.diffuse,
  1247. specular: materialCfg.specular,
  1248. glossiness: 0.5,
  1249. emissive: materialCfg.emissive,
  1250. alpha: materialCfg.alpha,
  1251. alphaMode: materialCfg.alphaMode
  1252. });
  1253. break;
  1254.  
  1255. default:
  1256. material = new xeogl.PhongMaterial(ctx.model.scene, {
  1257. reflectivity: 0.5,
  1258. ambient: materialCfg.ambient,
  1259. diffuse: materialCfg.diffuse,
  1260. specular: materialCfg.specular,
  1261. // shininess: node.shine,
  1262. emissive: materialCfg.emissive,
  1263. alphaMode: materialCfg.alphaMode,
  1264. alpha: node.alpha
  1265. });
  1266. }
  1267.  
  1268. ctx.model._addComponent(material);
  1269. return material;
  1270. }
  1271.  
  1272. break;
  1273. }
  1274. }
  1275. }
  1276.  
  1277. function parseRGB(str, coeff) {
  1278. coeff = (coeff !== undefined) ? coeff : 0.5;
  1279. var openBracketIndex = str.indexOf("[");
  1280. var closeBracketIndex = str.indexOf("]");
  1281. str = str.substring(openBracketIndex + 1, closeBracketIndex - openBracketIndex);
  1282. str = str.split(",");
  1283. var arr = new Float32Array(str.length);
  1284. var arrIdx = 0;
  1285. for (var i = 0, len = str.length; i < len; i++) {
  1286. var value = str[i];
  1287. value = value.split(" ");
  1288. for (var j = 0, lenj = value.length; j < lenj; j++) {
  1289. if (value[j] !== "") {
  1290. arr[arrIdx++] = parseFloat(value[j]) * coeff;
  1291. }
  1292. }
  1293. }
  1294. return arr;
  1295. }
  1296.  
  1297.  
  1298. //----------------------------------------------------------------------------------------------------
  1299.  
  1300. /**
  1301. * Wraps zip.js to provide an in-memory ZIP archive representing the 3DXML file bundle.
  1302. *
  1303. * Allows us to pluck each file from it as XML and JSON.
  1304. *
  1305. * @constructor
  1306. */
  1307. var ZIP = function () {
  1308.  
  1309. var reader;
  1310. var files = {};
  1311.  
  1312. /**
  1313. Loads this ZIP
  1314.  
  1315. @param src
  1316. @param ok
  1317. @param error
  1318. */
  1319. this.load = function (src, ok, error) {
  1320. var self = this;
  1321. zip.createReader(new zip.HttpReader(src), function (reader) {
  1322. reader.getEntries(function (entries) {
  1323. if (entries.length > 0) {
  1324. for (var i = 0, len = entries.length; i < len; i++) {
  1325. var entry = entries[i];
  1326. files[entry.filename] = entry;
  1327. }
  1328. }
  1329. ok();
  1330. });
  1331. }, error);
  1332. };
  1333.  
  1334. /**
  1335. Gets a file as XML and JSON from this ZIP
  1336. @param src
  1337. @param ok
  1338. @param error
  1339. */
  1340. this.getFile = function (src, ok, error) {
  1341. var entry = files[src];
  1342. if (!entry) {
  1343. var errMsg = "ZIP entry not found: " + src;
  1344. console.error(errMsg);
  1345. if (error) {
  1346. error(errMsg);
  1347. }
  1348. return;
  1349. }
  1350. entry.getData(new zip.TextWriter(), function (text) {
  1351.  
  1352. // Parse to XML
  1353. var parser = new DOMParser();
  1354. var xmlDoc = parser.parseFromString(text, "text/xml");
  1355.  
  1356. // Parse to JSON
  1357. var json = xmlToJSON(xmlDoc, {});
  1358.  
  1359. ok(xmlDoc, json);
  1360. });
  1361. };
  1362.  
  1363. function xmlToJSON(node, attributeRenamer) {
  1364. if (node.nodeType === node.TEXT_NODE) {
  1365. var v = node.nodeValue;
  1366. if (v.match(/^\s+$/) === null) {
  1367. return v;
  1368. }
  1369. } else if (node.nodeType === node.ELEMENT_NODE ||
  1370. node.nodeType === node.DOCUMENT_NODE) {
  1371. var json = {type: node.nodeName, children: []};
  1372. if (node.nodeType === node.ELEMENT_NODE) {
  1373. for (var j = 0; j < node.attributes.length; j++) {
  1374. var attribute = node.attributes[j];
  1375. var nm = attributeRenamer[attribute.nodeName] || attribute.nodeName;
  1376. json[nm] = attribute.nodeValue;
  1377. }
  1378. }
  1379. for (var i = 0; i < node.childNodes.length; i++) {
  1380. var item = node.childNodes[i];
  1381. var j = xmlToJSON(item, attributeRenamer);
  1382. if (j) json.children.push(j);
  1383. }
  1384. return json;
  1385. }
  1386. }
  1387.  
  1388. /**
  1389. Disposes of this ZIP
  1390. */
  1391. this.destroy = function () {
  1392. reader.close(function () {
  1393. // onclose callback
  1394. });
  1395. };
  1396. };
  1397.  
  1398. function loadZIP(src, ok, err) {
  1399. var zip = new ZIP();
  1400. zip.load(src, function () {
  1401. ok(zip);
  1402. }, function (errMsg) {
  1403. err("Error loading ZIP archive: " + errMsg);
  1404. })
  1405. }
  1406.  
  1407. // function loadXML(url, ok, err) {
  1408. // var request = new XMLHttpRequest();
  1409. // request.overrideMimeType("text/xml");
  1410. // request.open('GET', url, true);
  1411. // request.addEventListener('load', function (event) {
  1412. // //var response = event.target.response;
  1413. // if (this.status === 200) {
  1414. // if (ok) {
  1415. // var parser = new DOMParser();
  1416. // var xmlDoc = parser.parseFromString(request.responseText, "text/xml");
  1417. // ok(xmlDoc, this);
  1418. // }
  1419. // } else if (this.status === 0) {
  1420. // // Some browsers return HTTP Status 0 when using non-http protocol
  1421. // // e.g. 'file://' or 'data://'. Handle as success.
  1422. // console.warn('loadFile: HTTP Status 0 received.');
  1423. // if (ok) {
  1424. // var parser = new DOMParser();
  1425. // var xmlDoc = parser.parseFromString(request.responseText, "text/xml");
  1426. // ok(xmlDoc, this);
  1427. // }
  1428. // } else {
  1429. // if (err) {
  1430. // err(event);
  1431. // }
  1432. // }
  1433. // }, false);
  1434. //
  1435. // request.addEventListener('error', function (event) {
  1436. // if (err) {
  1437. // err(event);
  1438. // }
  1439. // }, false);
  1440. // request.send(null);
  1441. // }
  1442. //
  1443. // function xmlToJSON(node, attributeRenamer) {
  1444. // if (node.nodeType === node.TEXT_NODE) {
  1445. // var v = node.nodeValue;
  1446. // if (v.match(/^\s+$/) === null) {
  1447. // return v;
  1448. // }
  1449. // } else if (node.nodeType === node.ELEMENT_NODE ||
  1450. // node.nodeType === node.DOCUMENT_NODE) {
  1451. // var json = {type: node.nodeName, children: []};
  1452. // if (node.nodeType === node.ELEMENT_NODE) {
  1453. // for (var j = 0; j < node.attributes.length; j++) {
  1454. // var attribute = node.attributes[j];
  1455. // var nm = attributeRenamer[attribute.nodeName] || attribute.nodeName;
  1456. // json[nm] = attribute.nodeValue;
  1457. // }
  1458. // }
  1459. // for (var i = 0; i < node.childNodes.length; i++) {
  1460. // var item = node.childNodes[i];
  1461. // var j = xmlToJSON(item, attributeRenamer);
  1462. // if (j) json.children.push(j);
  1463. // }
  1464. // return json;
  1465. // }
  1466. // }
  1467.  
  1468. function stripURN(str) {
  1469. var subStr = "urn:3DXML:";
  1470. return (str.indexOf(subStr) === 0) ? str.substring(subStr.length) : str;
  1471. }
  1472.  
  1473.  
  1474. function getIDFromURI(str) {
  1475. var hashIdx = str.lastIndexOf("#");
  1476. return hashIdx != -1 ? str.substring(hashIdx + 1) : str;
  1477. }
  1478.  
  1479. })();