nuggt69

Untitled

Nov 17th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.10 KB | None | 0 0
  1. function unfreeze(obj) {
  2. var copy = {};
  3. for(var i in obj) {
  4. copy[i] = obj[i];
  5. }
  6. return copy;
  7. }
  8.  
  9. var models = [];
  10. var baseModelName = safeName(document.title.replace(' - Sketchfab', ''));
  11. function overrideDrawImplementation() {
  12. var geometry = OSG.osg.Geometry;
  13. var newPrototype = unfreeze(geometry.prototype);
  14. geometry.prototype = newPrototype;
  15. newPrototype.originalDrawImplementation = newPrototype.drawImplementation;
  16. newPrototype.drawImplementation = function(a) {
  17. this.originalDrawImplementation(a);
  18. if (!this.computedOBJ) {
  19. this.computedOBJ = true;
  20. this.name = baseModelName + '-' + models.length;
  21. this.__defineGetter__("textures", function() {
  22. return this._textures ? this._textures : this._textures = textureInfoForGeometry(this);
  23. });
  24. models.push({
  25. name: this.name,
  26. geom: this,
  27. get obj() {
  28. return OBJforGeometry(this.geom);
  29. },
  30. get mtl() {
  31. return MTLforGeometry(this.geom);
  32. },
  33. get textures() {
  34. return this.geom.textures;
  35. }
  36. });
  37. }
  38. };
  39. }
  40.  
  41. // source: http://stackoverflow.com/a/8485137
  42. function safeName(s) {
  43. return s.replace(/[^a-zA-Z0-9]/gi, '_').toLowerCase();
  44. }
  45.  
  46. function InfoForGeometry(geom) {
  47. var attributes = geom.attributes;
  48. if (!attributes)
  49. throw "No attributes for geometry";
  50. var vertices = attributes.Vertex;
  51. if (!vertices)
  52. throw "No vertices for geometry";
  53. var normals = attributes.Normal;
  54. var texCoords = attributes.TexCoord0;
  55. var info = {
  56. 'vertices' : vertices._elements,
  57. 'normals' : normals ? normals._elements : [],
  58. 'texCoords' : texCoords ? texCoords._elements : [],
  59. 'primitives' : [],
  60. 'name' : geom.name
  61. };
  62. for (i = 0; i < geom.primitives.length; ++i) {
  63. var primitive = geom.primitives[i];
  64. info.primitives.push({
  65. 'mode' : primitive.mode,
  66. 'indices' : primitive.indices._elements
  67. });
  68. }
  69. return info;
  70. }
  71.  
  72. var verticesExported = 0;
  73. var nl = '\n';
  74. function OBJforGeometry(geom) {
  75. var obj = '';
  76. var info = InfoForGeometry(geom);
  77. obj += 'mtllib ' + MTLFilenameForGeometry(geom) + nl;
  78. obj += 'o ' + geom.name + nl;
  79. for (i = 0; i < info.vertices.length; i += 3) {
  80. obj += 'v ';
  81. for (j = 0; j < 3; ++j) {
  82. obj += info.vertices[i + j] + ' ';
  83. }
  84. obj += nl;
  85. }
  86. for (i = 0; i < info.normals.length; i += 3) {
  87. obj += 'vn ';
  88. for (j = 0; j < 3; ++j) {
  89. obj += info.normals[i + j] + ' ';
  90. }
  91. obj += nl;
  92. }
  93. for (i = 0; i < info.texCoords.length; i += 2) {
  94. obj += 'vt ';
  95. for (j = 0; j < 2; ++j) {
  96. obj += info.texCoords[i + j] + ' ';
  97. }
  98. obj += nl;
  99. }
  100. obj += 'usemtl ' + MTLNameForGeometry(geom) + nl;
  101. obj += 's on' + nl;
  102. var exist = {
  103. normals: info.normals.length != 0,
  104. texCoords: info.texCoords.length != 0,
  105. };
  106. for (i = 0; i < info.primitives.length; ++i) {
  107. var primitive = info.primitives[i];
  108. if (primitive.mode == 4 || primitive.mode == 5) {
  109. var isTriangleStrip = primitive.mode == 5;
  110. for (j = 0; j + 2 < primitive.indices.length; !isTriangleStrip ? j += 3 : ++j) {
  111. obj += 'f ';
  112. var isOddFace = j % 2 == 1;
  113. var order = [ 0, 1, 2];
  114. if (isTriangleStrip && isOddFace)
  115. order = [ 0, 2, 1];
  116. for (k = 0; k < 3; ++k) {
  117. var faceNum = primitive.indices[j + order[k]] + 1 + verticesExported;
  118. obj += faceNum;
  119. if (exist.normals && !exist.texCoords) {
  120. obj += '//' + faceNum;
  121. }
  122. else {
  123. if (exist.texCoords) {
  124. obj += '/' + faceNum;
  125. }
  126. if (exist.normals) {
  127. obj += '/' + faceNum;
  128. }
  129. }
  130. obj += ' ';
  131. }
  132. obj += nl;
  133. }
  134. }
  135. else {
  136. throw 'Primitive mode not implemented';
  137. }
  138. }
  139. verticesExported += info.vertices.length / 3.0;
  140. return obj;
  141. }
  142.  
  143. var textureMTLMap = {
  144. DiffuseColor: "map_Kd",
  145. SpecularColor: "map_Ks",
  146. NormalMap : "map_bump",
  147. EmitColor : "map_Ke",
  148. AlphaMask : "map_d",
  149. Opacity : "map_o"
  150. };
  151.  
  152. // source: http://stackoverflow.com/a/3820412
  153. function baseName(str)
  154. {
  155. var base = new String(str).substring(str.lastIndexOf('/') + 1);
  156. if(base.lastIndexOf(".") != -1)
  157. base = base.substring(0, base.lastIndexOf("."));
  158. return base;
  159. }
  160.  
  161. function ext(str) {
  162. return str.split('.').pop();
  163. }
  164.  
  165. function textureInfoForGeometry(geom) {
  166. var textureMap = [];
  167. if (stateset = geom.stateset) {
  168. if (textures = stateset.textureAttributeMapList) {
  169. textures.forEach(function(texture) {
  170. if (Texture = texture.Texture) {
  171. if (object = Texture._object) {
  172. if (texture = object._texture) {
  173. if (imageProxy = texture._imageProxy) {
  174. var textureURL = imageProxy.attributes.images[0].url;
  175. var texture = {
  176. url: textureURL,
  177. type: textureMTLMap[object._channelName],
  178. ext: ext(textureURL)
  179. };
  180. texture.filename = textureFilename(geom, texture);
  181. textureMap.push(texture);
  182. }
  183. }
  184. }
  185. }
  186. });
  187. }
  188. }
  189. return textureMap;
  190. }
  191.  
  192. function textureFilename(geom, texture) {
  193. return baseName(texture.url) + '.' + texture.ext;
  194. }
  195.  
  196. function MTLFilenameForGeometry(geom) {
  197. return baseModelName + '.mtl';
  198. }
  199.  
  200. function MTLNameForGeometry(geom) {
  201. return geom.name;
  202. }
  203.  
  204. function MTLforGeometry(geom) {
  205. var mtl = '';
  206. mtl += 'newmtl ' + MTLNameForGeometry(geom) + nl;
  207. geom.textures.forEach(function(texture) {
  208. mtl += texture.type + ' ' + texture.filename + nl;
  209. });
  210. return mtl;
  211. }
  212.  
  213. // source: http://stackoverflow.com/questions/3219758/detect-changes-in-the-dom
  214. var observeDOM = (function(){
  215. var MutationObserver = window.MutationObserver || window.WebKitMutationObserver,
  216. eventListenerSupported = window.addEventListener;
  217.  
  218. return function(obj, callback){
  219. if( MutationObserver ){
  220. // define a new observer
  221. var obs = new MutationObserver(function(mutations, observer){
  222. if( mutations[0].addedNodes.length || mutations[0].removedNodes.length )
  223. callback();
  224. });
  225. // have the observer observe foo for changes in children
  226. obs.observe( obj, { childList:true, subtree:true });
  227. }
  228. else if( eventListenerSupported ){
  229. obj.addEventListener('DOMNodeInserted', callback, false);
  230. obj.addEventListener('DOMNodeRemoved', callback, false);
  231. }
  232. }
  233. })();
  234.  
  235.  
  236. // source: http://stackoverflow.com/questions/10596417/is-there-a-way-to-get-element-by-xpath-in-javascript
  237. function getElementByXpath(path) {
  238. return document.evaluate(path, document, null, 9, null).singleNodeValue;
  239. }
  240.  
  241. var addedDownloadButton = false;
  242. var downloadButtonParentXPath = "//div[@class='controls']";
  243. var osgScriptElementPath = "//script[contains (@src, 'sketchfab')]";
  244. var foundOsgScript = false;
  245.  
  246. observeDOM(document.body, function(){
  247. if (!foundOsgScript) {
  248. if (osgScript = getElementByXpath(osgScriptElementPath)) {
  249. overrideDrawImplementation();
  250. foundOsgScript = true;
  251. }
  252. }
  253. if (!addedDownloadButton) {
  254. if (downloadButtonParent = getElementByXpath(downloadButtonParentXPath))
  255. {
  256. setTimeout(function () {
  257. addDownloadButton(downloadButtonParent);
  258. }, 2000);
  259. addedDownloadButton = true;
  260. }
  261. }
  262. });
  263.  
  264. // source: http://thiscouldbebetter.wordpress.com/2012/12/18/loading-editing-and-saving-a-text-file-in-html5-using-javascrip/
  265. function downloadString(filename, ext, str) {
  266. function destroyClickedElement(event)
  267. {
  268. document.body.removeChild(event.target);
  269. }
  270. var textFileAsBlob = new Blob([str], {type:'text/plain'});
  271. var fileNameToSaveAs = filename + '.' + ext;
  272.  
  273. var downloadLink = document.createElement("a");
  274. downloadLink.download = fileNameToSaveAs;
  275. downloadLink.innerHTML = "Download File";
  276. if (window.webkitURL != null)
  277. {
  278. // Chrome allows the link to be clicked
  279. // without actually adding it to the DOM.
  280. downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
  281. }
  282. else
  283. {
  284. // Firefox requires the link to be added to the DOM
  285. // before it can be clicked.
  286. downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
  287. downloadLink.onclick = destroyClickedElement;
  288. downloadLink.style.display = "none";
  289. document.body.appendChild(downloadLink);
  290. }
  291. downloadLink.click();
  292. }
  293.  
  294. var imagesDownloaded = {};
  295. // source: http://muaz-khan.blogspot.com/2012/10/save-files-on-disk-using-javascript-or.html
  296. function downloadFileAtURL(fileURL) {
  297. if (!imagesDownloaded[fileURL]) {
  298. imagesDownloaded[fileURL] = true;
  299. var save = document.createElement('a');
  300. save.href = fileURL;
  301. save.target = '_blank';
  302. save.download = '';
  303. var event = document.createEvent('Event');
  304. event.initEvent('click', true, true);
  305. save.dispatchEvent(event);
  306. (window.URL || window.webkitURL).revokeObjectURL(save.href);
  307. }
  308. }
  309.  
  310. function downloadModels() {
  311. if (models.length == 0) {
  312. alert("Download script failed... try refreshing the page");
  313. return;
  314. }
  315. var combinedOBJ = '';
  316. var combinedMTL = '';
  317. models.forEach(function(model) {
  318. combinedOBJ += model.obj + nl;
  319. combinedMTL += model.mtl + nl;
  320. model.textures.forEach(function(texture) {
  321. downloadFileAtURL(texture.url);
  322. });
  323. });
  324. downloadString(baseModelName, 'obj', combinedOBJ);
  325. downloadString(baseModelName, 'mtl', combinedMTL);
  326. }
  327.  
  328. function addDownloadButton(downloadButtonParent) {
  329. var downloadButton = document.createElement("a");
  330. downloadButton.setAttribute("class", "control");
  331. downloadButton.innerHTML = "<pre>DOWNLOAD </pre>";
  332. downloadButton.addEventListener("click", downloadModels , false);
  333. downloadButtonParent.appendChild(downloadButton);
  334. }
Add Comment
Please, Sign In to add comment